|
@@ -7,7 +7,6 @@ import (
|
|
"golang.org/x/net/context"
|
|
"golang.org/x/net/context"
|
|
|
|
|
|
"github.com/docker/docker/pkg/pools"
|
|
"github.com/docker/docker/pkg/pools"
|
|
- "github.com/docker/docker/pkg/promise"
|
|
|
|
"github.com/docker/docker/pkg/term"
|
|
"github.com/docker/docker/pkg/term"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
)
|
|
@@ -58,7 +57,7 @@ func (c *Config) AttachStreams(cfg *AttachConfig) {
|
|
}
|
|
}
|
|
|
|
|
|
// CopyStreams starts goroutines to copy data in and out to/from the container
|
|
// CopyStreams starts goroutines to copy data in and out to/from the container
|
|
-func (c *Config) CopyStreams(ctx context.Context, cfg *AttachConfig) chan error {
|
|
|
|
|
|
+func (c *Config) CopyStreams(ctx context.Context, cfg *AttachConfig) <-chan error {
|
|
var (
|
|
var (
|
|
wg sync.WaitGroup
|
|
wg sync.WaitGroup
|
|
errors = make(chan error, 3)
|
|
errors = make(chan error, 3)
|
|
@@ -137,35 +136,42 @@ func (c *Config) CopyStreams(ctx context.Context, cfg *AttachConfig) chan error
|
|
go attachStream("stdout", cfg.Stdout, cfg.CStdout)
|
|
go attachStream("stdout", cfg.Stdout, cfg.CStdout)
|
|
go attachStream("stderr", cfg.Stderr, cfg.CStderr)
|
|
go attachStream("stderr", cfg.Stderr, cfg.CStderr)
|
|
|
|
|
|
- return promise.Go(func() error {
|
|
|
|
- done := make(chan struct{})
|
|
|
|
- go func() {
|
|
|
|
- wg.Wait()
|
|
|
|
- close(done)
|
|
|
|
- }()
|
|
|
|
- select {
|
|
|
|
- case <-done:
|
|
|
|
- case <-ctx.Done():
|
|
|
|
- // close all pipes
|
|
|
|
- if cfg.CStdin != nil {
|
|
|
|
- cfg.CStdin.Close()
|
|
|
|
- }
|
|
|
|
- if cfg.CStdout != nil {
|
|
|
|
- cfg.CStdout.Close()
|
|
|
|
- }
|
|
|
|
- if cfg.CStderr != nil {
|
|
|
|
- cfg.CStderr.Close()
|
|
|
|
|
|
+ errs := make(chan error, 1)
|
|
|
|
+
|
|
|
|
+ go func() {
|
|
|
|
+ defer close(errs)
|
|
|
|
+ errs <- func() error {
|
|
|
|
+ done := make(chan struct{})
|
|
|
|
+ go func() {
|
|
|
|
+ wg.Wait()
|
|
|
|
+ close(done)
|
|
|
|
+ }()
|
|
|
|
+ select {
|
|
|
|
+ case <-done:
|
|
|
|
+ case <-ctx.Done():
|
|
|
|
+ // close all pipes
|
|
|
|
+ if cfg.CStdin != nil {
|
|
|
|
+ cfg.CStdin.Close()
|
|
|
|
+ }
|
|
|
|
+ if cfg.CStdout != nil {
|
|
|
|
+ cfg.CStdout.Close()
|
|
|
|
+ }
|
|
|
|
+ if cfg.CStderr != nil {
|
|
|
|
+ cfg.CStderr.Close()
|
|
|
|
+ }
|
|
|
|
+ <-done
|
|
}
|
|
}
|
|
- <-done
|
|
|
|
- }
|
|
|
|
- close(errors)
|
|
|
|
- for err := range errors {
|
|
|
|
- if err != nil {
|
|
|
|
- return err
|
|
|
|
|
|
+ close(errors)
|
|
|
|
+ for err := range errors {
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
- return nil
|
|
|
|
- })
|
|
|
|
|
|
+ return nil
|
|
|
|
+ }()
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ return errs
|
|
}
|
|
}
|
|
|
|
|
|
func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64, err error) {
|
|
func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64, err error) {
|