Browse code

Fix race conditions in logs API

Closing the log driver was in a defer meanwhile logs are
collected asyncronously, so the log driver was being closed before reads
were actually finished.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2018/05/05 01:41:42
Showing 1 changed files
... ...
@@ -22,7 +22,7 @@ import (
22 22
 //
23 23
 // if it returns nil, the config channel will be active and return log
24 24
 // messages until it runs out or the context is canceled.
25
-func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, config *types.ContainerLogsOptions) (<-chan *backend.LogMessage, bool, error) {
25
+func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, config *types.ContainerLogsOptions) (messages <-chan *backend.LogMessage, isTTY bool, retErr error) {
26 26
 	lg := logrus.WithFields(logrus.Fields{
27 27
 		"module":    "daemon",
28 28
 		"method":    "(*Daemon).ContainerLogs",
... ...
@@ -51,8 +51,10 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
51 51
 	}
52 52
 	if cLogCreated {
53 53
 		defer func() {
54
-			if err = cLog.Close(); err != nil {
55
-				logrus.Errorf("Error closing logger: %v", err)
54
+			if retErr != nil {
55
+				if err = cLog.Close(); err != nil {
56
+					logrus.Errorf("Error closing logger: %v", err)
57
+				}
56 58
 			}
57 59
 		}()
58 60
 	}
... ...
@@ -101,6 +103,13 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
101 101
 	// this goroutine functions as a shim between the logger and the caller.
102 102
 	messageChan := make(chan *backend.LogMessage, 1)
103 103
 	go func() {
104
+		if cLogCreated {
105
+			defer func() {
106
+				if err = cLog.Close(); err != nil {
107
+					logrus.Errorf("Error closing logger: %v", err)
108
+				}
109
+			}()
110
+		}
104 111
 		// set up some defers
105 112
 		defer logs.Close()
106 113