From 96a54cbbd34c5c41c028466908738299b045f7e3 Mon Sep 17 00:00:00 2001 From: Mahmood Ali Date: Tue, 16 Apr 2019 10:48:25 -0400 Subject: [PATCH] locking and opening streams in goroutine comment --- drivers/docker/docklog/docker_logger.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/docker/docklog/docker_logger.go b/drivers/docker/docklog/docker_logger.go index 4174dd04c2a9..040ea78c6d5d 100644 --- a/drivers/docker/docklog/docker_logger.go +++ b/drivers/docker/docklog/docker_logger.go @@ -78,7 +78,7 @@ func (d *dockerLogger) Start(opts *StartOpts) error { go func() { defer close(d.doneCh) - stdout, stderr, err := d.openStreams(opts) + stdout, stderr, err := d.openStreams(ctx, opts) if err != nil { d.logger.Error("log streaming ended with terminal error", "error", err) return @@ -132,7 +132,9 @@ func (d *dockerLogger) Start(opts *StartOpts) error { } -func (d *dockerLogger) openStreams(opts *StartOpts) (stdout, stderr io.WriteCloser, err error) { +// openStreams open logger stdout/stderr; should be called in a background goroutine to avoid locking up +// process to avoid locking goroutine process +func (d *dockerLogger) openStreams(ctx context.Context, opts *StartOpts) (stdout, stderr io.WriteCloser, err error) { d.stdLock.Lock() stdoutF, stderrF := d.stdout, d.stderr d.stdLock.Unlock() @@ -141,6 +143,10 @@ func (d *dockerLogger) openStreams(opts *StartOpts) (stdout, stderr io.WriteClos return stdoutF, stderrF, nil } + // opening a fifo may block indefinitely until a reader end opens, so + // we preform open() without holding the stdLock, so Stop and interleave. + // This a defensive measure - logmon (the reader end) should be up and + // started before dockerLogger is started if stdoutF == nil { stdoutF, err = fifo.OpenWriter(opts.Stdout) if err != nil { @@ -155,6 +161,13 @@ func (d *dockerLogger) openStreams(opts *StartOpts) (stdout, stderr io.WriteClos } } + if ctx.Err() != nil { + // Stop was called and don't need files anymore + stdoutF.Close() + stderrF.Close() + return nil, nil, ctx.Err() + } + d.stdLock.Lock() d.stdout, d.stderr = stdoutF, stderrF d.stdLock.Unlock()