Browse code

Merge pull request #30223 from mlaventure/fix-logwatcher-deadlock

Close logwatcher on context cancellation
(cherry picked from commit 0566f3ffc46fbdf020e957fc30f56960152e057e)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Tõnis Tiigi authored on 2017/01/21 03:14:37
Showing 2 changed files
... ...
@@ -137,7 +137,11 @@ func tailFile(f io.ReadSeeker, logWatcher *logger.LogWatcher, tail int, since ti
137 137
 		if !since.IsZero() && msg.Timestamp.Before(since) {
138 138
 			continue
139 139
 		}
140
-		logWatcher.Msg <- msg
140
+		select {
141
+		case <-logWatcher.WatchClose():
142
+			return
143
+		case logWatcher.Msg <- msg:
144
+		}
141 145
 	}
142 146
 }
143 147
 
... ...
@@ -61,6 +61,18 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
61 61
 		Follow: follow,
62 62
 	}
63 63
 	logs := logReader.ReadLogs(readConfig)
64
+	// Close logWatcher on exit
65
+	defer func() {
66
+		logs.Close()
67
+		if cLog != container.LogDriver {
68
+			// Since the logger isn't cached in the container, which
69
+			// occurs if it is running, it must get explicitly closed
70
+			// here to avoid leaking it and any file handles it has.
71
+			if err := cLog.Close(); err != nil {
72
+				logrus.Errorf("Error closing logger: %v", err)
73
+			}
74
+		}
75
+	}()
64 76
 
65 77
 	wf := ioutils.NewWriteFlusher(config.OutStream)
66 78
 	defer wf.Close()
... ...
@@ -81,19 +93,11 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
81 81
 			logrus.Errorf("Error streaming logs: %v", err)
82 82
 			return nil
83 83
 		case <-ctx.Done():
84
-			logs.Close()
84
+			logrus.Debugf("logs: end stream, ctx is done: %v", ctx.Err())
85 85
 			return nil
86 86
 		case msg, ok := <-logs.Msg:
87 87
 			if !ok {
88 88
 				logrus.Debug("logs: end stream")
89
-				logs.Close()
90
-				if cLog != container.LogDriver {
91
-					// Since the logger isn't cached in the container, which occurs if it is running, it
92
-					// must get explicitly closed here to avoid leaking it and any file handles it has.
93
-					if err := cLog.Close(); err != nil {
94
-						logrus.Errorf("Error closing logger: %v", err)
95
-					}
96
-				}
97 89
 				return nil
98 90
 			}
99 91
 			logLine := msg.Line