1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Use waitgroup instead of iterating errors chan

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff 2015-01-05 17:30:38 -08:00
parent 21e44d7a21
commit e6c9343457

View file

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"os" "os"
"sync"
"time" "time"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
@ -114,62 +115,63 @@ func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, t
var ( var (
cStdout, cStderr io.ReadCloser cStdout, cStderr io.ReadCloser
cStdin io.WriteCloser cStdin io.WriteCloser
nJobs int wg sync.WaitGroup
errors = make(chan error, 3)
) )
if stdin != nil && openStdin { if stdin != nil && openStdin {
cStdin = streamConfig.StdinPipe() cStdin = streamConfig.StdinPipe()
nJobs++ wg.Add(1)
} }
if stdout != nil { if stdout != nil {
cStdout = streamConfig.StdoutPipe() cStdout = streamConfig.StdoutPipe()
nJobs++ wg.Add(1)
} }
if stderr != nil { if stderr != nil {
cStderr = streamConfig.StderrPipe() cStderr = streamConfig.StderrPipe()
nJobs++ wg.Add(1)
} }
errors := make(chan error, nJobs)
// Connect stdin of container to the http conn. // Connect stdin of container to the http conn.
if stdin != nil && openStdin { go func() {
// Get the stdin pipe. if stdin == nil || !openStdin {
cStdin = streamConfig.StdinPipe() return
go func() { }
log.Debugf("attach: stdin: begin") log.Debugf("attach: stdin: begin")
defer func() { defer func() {
if stdinOnce && !tty { if stdinOnce && !tty {
defer cStdin.Close() cStdin.Close()
} else {
// No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
if cStdout != nil {
cStdout.Close()
}
if cStderr != nil {
cStderr.Close()
}
}
log.Debugf("attach: stdin: end")
}()
var err error
if tty {
_, err = utils.CopyEscapable(cStdin, stdin)
} else { } else {
_, err = io.Copy(cStdin, stdin) // No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
if cStdout != nil {
cStdout.Close()
}
if cStderr != nil {
cStderr.Close()
}
} }
if err == io.ErrClosedPipe { wg.Done()
err = nil log.Debugf("attach: stdin: end")
}
if err != nil {
log.Errorf("attach: stdin: %s", err)
}
errors <- err
}() }()
}
var err error
if tty {
_, err = utils.CopyEscapable(cStdin, stdin)
} else {
_, err = io.Copy(cStdin, stdin)
}
if err == io.ErrClosedPipe {
err = nil
}
if err != nil {
log.Errorf("attach: stdin: %s", err)
errors <- err
return
}
}()
attachStream := func(name string, stream io.Writer, streamPipe io.ReadCloser) { attachStream := func(name string, stream io.Writer, streamPipe io.ReadCloser) {
if stream == nil { if stream == nil {
@ -182,34 +184,32 @@ func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, t
cStdin.Close() cStdin.Close()
} }
streamPipe.Close() streamPipe.Close()
wg.Done()
log.Debugf("attach: %s: end", name)
}() }()
log.Debugf("attach: %s: begin", name) log.Debugf("attach: %s: begin", name)
defer log.Debugf("attach: %s: end", name)
_, err := io.Copy(stream, streamPipe) _, err := io.Copy(stream, streamPipe)
if err == io.ErrClosedPipe { if err == io.ErrClosedPipe {
err = nil err = nil
} }
if err != nil { if err != nil {
log.Errorf("attach: %s: %v", name, err) log.Errorf("attach: %s: %v", name, err)
errors <- err
} }
errors <- err
} }
go attachStream("stdout", stdout, cStdout) go attachStream("stdout", stdout, cStdout)
go attachStream("stderr", stderr, cStderr) go attachStream("stderr", stderr, cStderr)
return promise.Go(func() error { return promise.Go(func() error {
for i := 0; i < nJobs; i++ { wg.Wait()
log.Debugf("attach: waiting for job %d/%d", i+1, nJobs) close(errors)
err := <-errors for err := range errors {
if err != nil { if err != nil {
log.Errorf("attach: job %d returned error %s, aborting all jobs", i+1, err)
return err return err
} }
log.Debugf("attach: job %d completed successfully", i+1)
} }
log.Debugf("attach: all jobs completed successfully")
return nil return nil
}) })
} }