From 90c272a4f20d60e795c0dfb950692093daebc97e Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Mon, 27 Jun 2016 14:14:17 -0700 Subject: [PATCH] daemon/logger: fix races in channel close it's actually not okay to do such trick from multiple goroutines Signed-off-by: Alexander Morozov (cherry picked from commit 378f0657f963fa6c854643571e4fe83628466c01) --- daemon/logger/copier.go | 15 +++++++-------- daemon/logger/logger.go | 8 ++++---- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/daemon/logger/copier.go b/daemon/logger/copier.go index 9abb59a176..a54f23f28d 100644 --- a/daemon/logger/copier.go +++ b/daemon/logger/copier.go @@ -14,10 +14,11 @@ import ( // Writes are concurrent, so you need implement some sync in your logger type Copier struct { // srcs is map of name -> reader pairs, for example "stdout", "stderr" - srcs map[string]io.Reader - dst Logger - copyJobs sync.WaitGroup - closed chan struct{} + srcs map[string]io.Reader + dst Logger + copyJobs sync.WaitGroup + closeOnce sync.Once + closed chan struct{} } // NewCopier creates a new Copier @@ -74,9 +75,7 @@ func (c *Copier) Wait() { // Close closes the copier func (c *Copier) Close() { - select { - case <-c.closed: - default: + c.closeOnce.Do(func() { close(c.closed) - } + }) } diff --git a/daemon/logger/logger.go b/daemon/logger/logger.go index fb8c9a7dee..77c6c90ce0 100644 --- a/daemon/logger/logger.go +++ b/daemon/logger/logger.go @@ -11,6 +11,7 @@ import ( "errors" "sort" "strings" + "sync" "time" "github.com/docker/docker/pkg/jsonlog" @@ -83,6 +84,7 @@ type LogWatcher struct { Msg chan *Message // For sending error messages that occur while while reading logs. Err chan error + closeOnce sync.Once closeNotifier chan struct{} } @@ -98,11 +100,9 @@ func NewLogWatcher() *LogWatcher { // Close notifies the underlying log reader to stop. func (w *LogWatcher) Close() { // only close if not already closed - select { - case <-w.closeNotifier: - default: + w.closeOnce.Do(func() { close(w.closeNotifier) - } + }) } // WatchClose returns a channel receiver that receives notification