Browse code

Fix race on ContainerAttachRaw

Signed-off-by: Jim Minter <jminter@redhat.com>

Jim Minter authored on 2017/03/15 20:33:04
Showing 4 changed files
... ...
@@ -114,7 +114,7 @@ type Backend interface {
114 114
 	// PullOnBuild tells Docker to pull image referenced by `name`.
115 115
 	PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (Image, error)
116 116
 	// ContainerAttachRaw attaches to container.
117
-	ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error
117
+	ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error
118 118
 	// ContainerCreate creates a new Docker container and returns potential warnings
119 119
 	ContainerCreate(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error)
120 120
 	// ContainerRm removes a container specified by `id`.
... ...
@@ -573,11 +573,18 @@ func (b *Builder) create() (string, error) {
573 573
 var errCancelled = errors.New("build cancelled")
574 574
 
575 575
 func (b *Builder) run(cID string) (err error) {
576
+	attached := make(chan struct{})
576 577
 	errCh := make(chan error)
577 578
 	go func() {
578
-		errCh <- b.docker.ContainerAttachRaw(cID, nil, b.Stdout, b.Stderr, true)
579
+		errCh <- b.docker.ContainerAttachRaw(cID, nil, b.Stdout, b.Stderr, true, attached)
579 580
 	}()
580 581
 
582
+	select {
583
+	case err := <-errCh:
584
+		return err
585
+	case <-attached:
586
+	}
587
+
581 588
 	finished := make(chan struct{})
582 589
 	cancelErrCh := make(chan error, 1)
583 590
 	go func() {
... ...
@@ -33,7 +33,7 @@ func (m *MockBackend) PullOnBuild(ctx context.Context, name string, authConfigs
33 33
 	return nil, nil
34 34
 }
35 35
 
36
-func (m *MockBackend) ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error {
36
+func (m *MockBackend) ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error {
37 37
 	return nil
38 38
 }
39 39
 
... ...
@@ -73,7 +73,7 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, c *backend.ContainerA
73 73
 }
74 74
 
75 75
 // ContainerAttachRaw attaches the provided streams to the container's stdio
76
-func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadCloser, stdout, stderr io.Writer, doStream bool) error {
76
+func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadCloser, stdout, stderr io.Writer, doStream bool, attached chan struct{}) error {
77 77
 	container, err := daemon.GetContainer(prefixOrName)
78 78
 	if err != nil {
79 79
 		return err
... ...
@@ -86,6 +86,7 @@ func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadClose
86 86
 		CloseStdin: container.Config.StdinOnce,
87 87
 	}
88 88
 	container.StreamConfig.AttachStreams(&cfg)
89
+	close(attached)
89 90
 	if cfg.UseStdin {
90 91
 		cfg.Stdin = stdin
91 92
 	}