Browse code

Fix race on sending stdin close event

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>

Tonis Tiigi authored on 2016/11/22 07:10:34
Showing 2 changed files
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"bytes"
6 6
 	"encoding/json"
7 7
 	"fmt"
8
+	"io"
8 9
 	"io/ioutil"
9 10
 	"net"
10 11
 	"os"
... ...
@@ -4849,3 +4850,32 @@ func (s *DockerSuite) TestRunEmptyEnv(c *check.C) {
4849 4849
 	c.Assert(err, checker.NotNil)
4850 4850
 	c.Assert(out, checker.Contains, expectedOutput)
4851 4851
 }
4852
+
4853
+// #28658
4854
+func (s *DockerSuite) TestSlowStdinClosing(c *check.C) {
4855
+	name := "testslowstdinclosing"
4856
+	repeat := 3 // regression happened 50% of the time
4857
+	for i := 0; i < repeat; i++ {
4858
+		cmd := exec.Command(dockerBinary, "run", "--rm", "--name", name, "-i", "busybox", "cat")
4859
+		cmd.Stdin = &delayedReader{}
4860
+		done := make(chan error, 1)
4861
+		go func() {
4862
+			_, err := runCommand(cmd)
4863
+			done <- err
4864
+		}()
4865
+
4866
+		select {
4867
+		case <-time.After(15 * time.Second):
4868
+			c.Fatal("running container timed out") // cleanup in teardown
4869
+		case err := <-done:
4870
+			c.Assert(err, checker.IsNil)
4871
+		}
4872
+	}
4873
+}
4874
+
4875
+type delayedReader struct{}
4876
+
4877
+func (s *delayedReader) Read([]byte) (int, error) {
4878
+	time.Sleep(500 * time.Millisecond)
4879
+	return 0, io.EOF
4880
+}
... ...
@@ -118,10 +118,14 @@ func (ctr *container) start(checkpoint string, checkpointDir string, attachStdio
118 118
 			go func() {
119 119
 				select {
120 120
 				case <-ready:
121
+				case <-ctx.Done():
122
+				}
123
+				select {
124
+				case <-ready:
121 125
 					if err := ctr.sendCloseStdin(); err != nil {
122 126
 						logrus.Warnf("failed to close stdin: %+v", err)
123 127
 					}
124
-				case <-ctx.Done():
128
+				default:
125 129
 				}
126 130
 			}()
127 131
 		})