|
@@ -83,7 +83,6 @@ func (daemon *Daemon) ContainerAttach(job *engine.Job) engine.Status {
|
|
var (
|
|
var (
|
|
cStdin io.ReadCloser
|
|
cStdin io.ReadCloser
|
|
cStdout, cStderr io.Writer
|
|
cStdout, cStderr io.Writer
|
|
- cStdinCloser io.Closer
|
|
|
|
)
|
|
)
|
|
|
|
|
|
if stdin {
|
|
if stdin {
|
|
@@ -94,7 +93,6 @@ func (daemon *Daemon) ContainerAttach(job *engine.Job) engine.Status {
|
|
io.Copy(w, job.Stdin)
|
|
io.Copy(w, job.Stdin)
|
|
}()
|
|
}()
|
|
cStdin = r
|
|
cStdin = r
|
|
- cStdinCloser = job.Stdin
|
|
|
|
}
|
|
}
|
|
if stdout {
|
|
if stdout {
|
|
cStdout = job.Stdout
|
|
cStdout = job.Stdout
|
|
@@ -103,7 +101,7 @@ func (daemon *Daemon) ContainerAttach(job *engine.Job) engine.Status {
|
|
cStderr = job.Stderr
|
|
cStderr = job.Stderr
|
|
}
|
|
}
|
|
|
|
|
|
- <-daemon.attach(&container.StreamConfig, container.Config.OpenStdin, container.Config.StdinOnce, container.Config.Tty, cStdin, cStdinCloser, cStdout, cStderr)
|
|
|
|
|
|
+ <-daemon.attach(&container.StreamConfig, container.Config.OpenStdin, container.Config.StdinOnce, container.Config.Tty, cStdin, cStdout, cStderr)
|
|
// If we are in stdinonce mode, wait for the process to end
|
|
// If we are in stdinonce mode, wait for the process to end
|
|
// otherwise, simply return
|
|
// otherwise, simply return
|
|
if container.Config.StdinOnce && !container.Config.Tty {
|
|
if container.Config.StdinOnce && !container.Config.Tty {
|
|
@@ -113,7 +111,7 @@ func (daemon *Daemon) ContainerAttach(job *engine.Job) engine.Status {
|
|
return engine.StatusOK
|
|
return engine.StatusOK
|
|
}
|
|
}
|
|
|
|
|
|
-func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdinCloser io.Closer, stdout io.Writer, stderr io.Writer) chan error {
|
|
|
|
|
|
+func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error {
|
|
var (
|
|
var (
|
|
cStdout, cStderr io.ReadCloser
|
|
cStdout, cStderr io.ReadCloser
|
|
nJobs int
|
|
nJobs int
|
|
@@ -130,10 +128,10 @@ func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, t
|
|
go func() {
|
|
go func() {
|
|
log.Debugf("attach: stdin: begin")
|
|
log.Debugf("attach: stdin: begin")
|
|
defer log.Debugf("attach: stdin: end")
|
|
defer log.Debugf("attach: stdin: end")
|
|
- // No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
|
|
|
|
if stdinOnce && !tty {
|
|
if stdinOnce && !tty {
|
|
defer cStdin.Close()
|
|
defer cStdin.Close()
|
|
} else {
|
|
} else {
|
|
|
|
+ // No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
|
|
defer func() {
|
|
defer func() {
|
|
if cStdout != nil {
|
|
if cStdout != nil {
|
|
cStdout.Close()
|
|
cStdout.Close()
|
|
@@ -173,9 +171,6 @@ func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, t
|
|
if stdinOnce && stdin != nil {
|
|
if stdinOnce && stdin != nil {
|
|
defer stdin.Close()
|
|
defer stdin.Close()
|
|
}
|
|
}
|
|
- if stdinCloser != nil {
|
|
|
|
- defer stdinCloser.Close()
|
|
|
|
- }
|
|
|
|
_, err := io.Copy(stdout, cStdout)
|
|
_, err := io.Copy(stdout, cStdout)
|
|
if err == io.ErrClosedPipe {
|
|
if err == io.ErrClosedPipe {
|
|
err = nil
|
|
err = nil
|
|
@@ -189,9 +184,6 @@ func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, t
|
|
} else {
|
|
} else {
|
|
// Point stdout of container to a no-op writer.
|
|
// Point stdout of container to a no-op writer.
|
|
go func() {
|
|
go func() {
|
|
- if stdinCloser != nil {
|
|
|
|
- defer stdinCloser.Close()
|
|
|
|
- }
|
|
|
|
if cStdout, err := streamConfig.StdoutPipe(); err != nil {
|
|
if cStdout, err := streamConfig.StdoutPipe(); err != nil {
|
|
log.Errorf("attach: stdout pipe: %s", err)
|
|
log.Errorf("attach: stdout pipe: %s", err)
|
|
} else {
|
|
} else {
|
|
@@ -213,9 +205,6 @@ func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, t
|
|
if stdinOnce && stdin != nil {
|
|
if stdinOnce && stdin != nil {
|
|
defer stdin.Close()
|
|
defer stdin.Close()
|
|
}
|
|
}
|
|
- if stdinCloser != nil {
|
|
|
|
- defer stdinCloser.Close()
|
|
|
|
- }
|
|
|
|
_, err := io.Copy(stderr, cStderr)
|
|
_, err := io.Copy(stderr, cStderr)
|
|
if err == io.ErrClosedPipe {
|
|
if err == io.ErrClosedPipe {
|
|
err = nil
|
|
err = nil
|
|
@@ -229,10 +218,6 @@ func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, t
|
|
} else {
|
|
} else {
|
|
// Point stderr at a no-op writer.
|
|
// Point stderr at a no-op writer.
|
|
go func() {
|
|
go func() {
|
|
- if stdinCloser != nil {
|
|
|
|
- defer stdinCloser.Close()
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if cStderr, err := streamConfig.StderrPipe(); err != nil {
|
|
if cStderr, err := streamConfig.StderrPipe(); err != nil {
|
|
log.Errorf("attach: stdout pipe: %s", err)
|
|
log.Errorf("attach: stdout pipe: %s", err)
|
|
} else {
|
|
} else {
|
|
@@ -251,8 +236,6 @@ func (daemon *Daemon) attach(streamConfig *StreamConfig, openStdin, stdinOnce, t
|
|
}
|
|
}
|
|
}()
|
|
}()
|
|
|
|
|
|
- // FIXME: how to clean up the stdin goroutine without the unwanted side effect
|
|
|
|
- // of closing the passed stdin? Add an intermediary io.Pipe?
|
|
|
|
for i := 0; i < nJobs; i++ {
|
|
for i := 0; i < nJobs; i++ {
|
|
log.Debugf("attach: waiting for job %d/%d", i+1, nJobs)
|
|
log.Debugf("attach: waiting for job %d/%d", i+1, nJobs)
|
|
if err := <-errors; err != nil {
|
|
if err := <-errors; err != nil {
|