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.
@@ -22,7 +22,7 @@ import (
//
// if it returns nil, the config channel will be active and return log
// messages until it runs out or the context is canceled.
-func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, config *types.ContainerLogsOptions) (<-chan *backend.LogMessage, bool, error) {
+func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, config *types.ContainerLogsOptions) (messages <-chan *backend.LogMessage, isTTY bool, retErr error) {
lg := logrus.WithFields(logrus.Fields{
"module": "daemon",
"method": "(*Daemon).ContainerLogs",
@@ -51,9 +51,11 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
}
if cLogCreated {
defer func() {
+ if retErr != nil {
if err = cLog.Close(); err != nil {
logrus.Errorf("Error closing logger: %v", err)
}
+ }
}()
}
@@ -101,6 +103,13 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
// this goroutine functions as a shim between the logger and the caller.
messageChan := make(chan *backend.LogMessage, 1)
go func() {
+ if cLogCreated {
+ defer func() {
+ if err = cLog.Close(); err != nil {
+ logrus.Errorf("Error closing logger: %v", err)
+ }
+ }()
+ }
// set up some defers
defer logs.Close()
