diff --git a/builder/builder.go b/builder/builder.go index f7a4f91f27..e6edc85c82 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -114,7 +114,7 @@ type Backend interface { // PullOnBuild tells Docker to pull image referenced by `name`. PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (Image, error) // ContainerAttachRaw attaches to container. - ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error + ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error // ContainerCreate creates a new Docker container and returns potential warnings ContainerCreate(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error) // ContainerRm removes a container specified by `id`. diff --git a/builder/dockerfile/internals.go b/builder/dockerfile/internals.go index e4e59e87f8..4ef7beb08c 100644 --- a/builder/dockerfile/internals.go +++ b/builder/dockerfile/internals.go @@ -573,11 +573,18 @@ func (b *Builder) create() (string, error) { var errCancelled = errors.New("build cancelled") func (b *Builder) run(cID string) (err error) { + attached := make(chan struct{}) errCh := make(chan error) go func() { - errCh <- b.docker.ContainerAttachRaw(cID, nil, b.Stdout, b.Stderr, true) + errCh <- b.docker.ContainerAttachRaw(cID, nil, b.Stdout, b.Stderr, true, attached) }() + select { + case err := <-errCh: + return err + case <-attached: + } + finished := make(chan struct{}) cancelErrCh := make(chan error, 1) go func() { diff --git a/builder/dockerfile/mockbackend_test.go b/builder/dockerfile/mockbackend_test.go index 4c03569678..d64125b082 100644 --- a/builder/dockerfile/mockbackend_test.go +++ b/builder/dockerfile/mockbackend_test.go @@ -33,7 +33,7 @@ func (m *MockBackend) PullOnBuild(ctx context.Context, name string, authConfigs return nil, nil } -func (m *MockBackend) ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error { +func (m *MockBackend) ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error { return nil } diff --git a/daemon/attach.go b/daemon/attach.go index fb213132f8..a0e2b700ae 100644 --- a/daemon/attach.go +++ b/daemon/attach.go @@ -73,7 +73,7 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, c *backend.ContainerA } // ContainerAttachRaw attaches the provided streams to the container's stdio -func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadCloser, stdout, stderr io.Writer, doStream bool) error { +func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadCloser, stdout, stderr io.Writer, doStream bool, attached chan struct{}) error { container, err := daemon.GetContainer(prefixOrName) if err != nil { return err @@ -86,6 +86,7 @@ func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadClose CloseStdin: container.Config.StdinOnce, } container.StreamConfig.AttachStreams(&cfg) + close(attached) if cfg.UseStdin { cfg.Stdin = stdin }