Skip to content

Commit fea7209

Browse files
committed
Fix race on sending stdin close event
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com> (cherry picked from commit 4e262f6)
1 parent 58a5164 commit fea7209

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

integration-cli/docker_cli_run_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bufio"
55
"bytes"
66
"fmt"
7+
"io"
78
"io/ioutil"
89
"net"
910
"os"
@@ -4467,3 +4468,32 @@ func (s *DockerSuite) TestRunStoppedLoggingDriverNoLeak(c *check.C) {
44674468
// NGoroutines is not updated right away, so we need to wait before failing
44684469
c.Assert(waitForGoroutines(nroutines), checker.IsNil)
44694470
}
4471+
4472+
// #28658
4473+
func (s *DockerSuite) TestSlowStdinClosing(c *check.C) {
4474+
name := "testslowstdinclosing"
4475+
repeat := 3 // regression happened 50% of the time
4476+
for i := 0; i < repeat; i++ {
4477+
cmd := exec.Command(dockerBinary, "run", "--rm", "--name", name, "-i", "busybox", "cat")
4478+
cmd.Stdin = &delayedReader{}
4479+
done := make(chan error, 1)
4480+
go func() {
4481+
_, err := runCommand(cmd)
4482+
done <- err
4483+
}()
4484+
4485+
select {
4486+
case <-time.After(15 * time.Second):
4487+
c.Fatal("running container timed out") // cleanup in teardown
4488+
case err := <-done:
4489+
c.Assert(err, checker.IsNil)
4490+
}
4491+
}
4492+
}
4493+
4494+
type delayedReader struct{}
4495+
4496+
func (s *delayedReader) Read([]byte) (int, error) {
4497+
time.Sleep(500 * time.Millisecond)
4498+
return 0, io.EOF
4499+
}

libcontainerd/container_linux.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,16 @@ func (ctr *container) start(attachStdio StdioCallback) error {
115115
stdinOnce.Do(func() { // on error from attach we don't know if stdin was already closed
116116
err = stdin.Close()
117117
go func() {
118+
select {
119+
case <-ready:
120+
case <-ctx.Done():
121+
}
118122
select {
119123
case <-ready:
120124
if err := ctr.sendCloseStdin(); err != nil {
121125
logrus.Warnf("failed to close stdin: %+v", err)
122126
}
123-
case <-ctx.Done():
127+
default:
124128
}
125129
}()
126130
})

0 commit comments

Comments
 (0)