Browse code

Close stdin after execution with `docker exec -i`

Docker-DCO-1.1-Signed-off-by: Erik Hollensbe <github@hollensbe.org> (github: erikh)

Erik Hollensbe authored on 2014/11/06 08:12:24
Showing 2 changed files
... ...
@@ -203,7 +203,7 @@ func (d *Daemon) ContainerExecStart(job *engine.Job) engine.Status {
203 203
 		execConfig.StreamConfig.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
204 204
 	}
205 205
 
206
-	attachErr := d.attach(&execConfig.StreamConfig, execConfig.OpenStdin, false, execConfig.ProcessConfig.Tty, cStdin, cStdout, cStderr)
206
+	attachErr := d.attach(&execConfig.StreamConfig, execConfig.OpenStdin, true, execConfig.ProcessConfig.Tty, cStdin, cStdout, cStderr)
207 207
 
208 208
 	execErr := make(chan error)
209 209
 
... ...
@@ -2,6 +2,7 @@ package main
2 2
 
3 3
 import (
4 4
 	"bufio"
5
+	"os"
5 6
 	"os/exec"
6 7
 	"strings"
7 8
 	"testing"
... ...
@@ -31,6 +32,47 @@ func TestExec(t *testing.T) {
31 31
 	logDone("exec - basic test")
32 32
 }
33 33
 
34
+func TestExecInteractiveStdinClose(t *testing.T) {
35
+	defer deleteAllContainers()
36
+	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-itd", "busybox", "/bin/cat"))
37
+	if err != nil {
38
+		t.Fatal(err)
39
+	}
40
+
41
+	contId := strings.TrimSpace(out)
42
+	println(contId)
43
+
44
+	returnchan := make(chan struct{})
45
+
46
+	go func() {
47
+		var err error
48
+		cmd := exec.Command(dockerBinary, "exec", "-i", contId, "/bin/ls", "/")
49
+		cmd.Stdin = os.Stdin
50
+		if err != nil {
51
+			t.Fatal(err)
52
+		}
53
+
54
+		out, err := cmd.CombinedOutput()
55
+		if err != nil {
56
+			t.Fatal(err, out)
57
+		}
58
+
59
+		if string(out) == "" {
60
+			t.Fatalf("Output was empty, likely blocked by standard input")
61
+		}
62
+
63
+		returnchan <- struct{}{}
64
+	}()
65
+
66
+	select {
67
+	case <-returnchan:
68
+	case <-time.After(10 * time.Second):
69
+		t.Fatal("timed out running docker exec")
70
+	}
71
+
72
+	logDone("exec - interactive mode closes stdin after execution")
73
+}
74
+
34 75
 func TestExecInteractive(t *testing.T) {
35 76
 	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && sleep 100")
36 77
 	if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {