daemon/logger: fix races in channel close

it's actually not okay to do such trick from multiple goroutines

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
This commit is contained in:
Alexander Morozov 2016-06-27 14:14:17 -07:00
parent ee658a5aa5
commit 378f0657f9
2 changed files with 11 additions and 12 deletions

View file

@ -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)
}
})
}

View file

@ -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