Browse code

Close logwatcher on context cancellation

This commit addresses 2 issues:

1. in `tailfile()` if somehow the `logWatcher.Msg` were to become full and the watcher closed before space was made into it, we were getting stuck there forever since we were not checking for the watcher getting closed
2. when servicing `docker logs`, if the command was cancelled we were not closing the watcher (and hence notifying it to stop copying data)

Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>

Kenfe-Mickael Laventure authored on 2017/01/18 06:12:50
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
 
... ...
@@ -64,6 +64,18 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
64 64
 		Follow: follow,
65 65
 	}
66 66
 	logs := logReader.ReadLogs(readConfig)
67
+	// Close logWatcher on exit
68
+	defer func() {
69
+		logs.Close()
70
+		if cLog != container.LogDriver {
71
+			// Since the logger isn't cached in the container, which
72
+			// occurs if it is running, it must get explicitly closed
73
+			// here to avoid leaking it and any file handles it has.
74
+			if err := cLog.Close(); err != nil {
75
+				logrus.Errorf("Error closing logger: %v", err)
76
+			}
77
+		}
78
+	}()
67 79
 
68 80
 	wf := ioutils.NewWriteFlusher(config.OutStream)
69 81
 	defer wf.Close()
... ...
@@ -84,19 +96,11 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
84 84
 			logrus.Errorf("Error streaming logs: %v", err)
85 85
 			return nil
86 86
 		case <-ctx.Done():
87
-			logs.Close()
87
+			logrus.Debugf("logs: end stream, ctx is done: %v", ctx.Err())
88 88
 			return nil
89 89
 		case msg, ok := <-logs.Msg:
90 90
 			if !ok {
91 91
 				logrus.Debug("logs: end stream")
92
-				logs.Close()
93
-				if cLog != container.LogDriver {
94
-					// Since the logger isn't cached in the container, which occurs if it is running, it
95
-					// must get explicitly closed here to avoid leaking it and any file handles it has.
96
-					if err := cLog.Close(); err != nil {
97
-						logrus.Errorf("Error closing logger: %v", err)
98
-					}
99
-				}
100 92
 				return nil
101 93
 			}
102 94
 			logLine := msg.Line