Skip to content

Commit f4bb939

Browse files
committed
attach: wait for exit code from ContainerWait
Such as with `docker run`, if a user CTRL-Cs while attached to a container, we should forward the signal and wait for the exit from `ContainerWait`, instead of just returning. Signed-off-by: Laura Brehm <laurabrehm@hey.com>
1 parent 788e996 commit f4bb939

3 files changed

Lines changed: 28 additions & 5 deletions

File tree

cli/command/container/attach.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o
7272
apiClient := dockerCLI.Client()
7373

7474
// request channel to wait for client
75-
resultC, errC := apiClient.ContainerWait(ctx, containerID, "")
75+
waitCtx := context.WithoutCancel(ctx)
76+
resultC, errC := apiClient.ContainerWait(waitCtx, containerID, "")
7677

7778
c, err := inspectContainerAndCheckState(ctx, apiClient, containerID)
7879
if err != nil {
@@ -163,9 +164,6 @@ func getExitStatus(errC <-chan error, resultC <-chan container.WaitResponse) err
163164
return cli.StatusError{StatusCode: int(result.StatusCode)}
164165
}
165166
case err := <-errC:
166-
if errors.Is(err, context.Canceled) {
167-
return nil
168-
}
169167
return err
170168
}
171169

cli/command/container/attach_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,11 @@ func TestGetExitStatus(t *testing.T) {
119119
expectedError: cli.StatusError{StatusCode: 15},
120120
},
121121
{
122+
result: &container.WaitResponse{
123+
StatusCode: 130,
124+
},
122125
err: context.Canceled,
123-
expectedError: nil,
126+
expectedError: cli.StatusError{StatusCode: 130},
124127
},
125128
}
126129

e2e/container/attach_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,28 @@ func TestAttachInterrupt(t *testing.T) {
4848
time.Sleep(500 * time.Millisecond)
4949
c.Process.Signal(os.Interrupt)
5050

51+
_ = c.Wait()
52+
assert.Equal(t, c.ProcessState.ExitCode(), 130)
53+
assert.Equal(t, d.String(), "")
54+
}
55+
56+
func TestAttachInterruptWithoutStdin(t *testing.T) {
57+
result := icmd.RunCommand("docker", "run", "-dit", fixtures.AlpineImage, "sh", "-c", "sleep 5")
58+
result.Assert(t, icmd.Success)
59+
containerID := strings.TrimSpace(result.Stdout())
60+
61+
// run it as such so we can signal it later
62+
c := exec.Command("docker", "attach", containerID)
63+
d := bytes.Buffer{}
64+
c.Stdout = &d
65+
c.Stderr = &d
66+
_, err := pty.Start(c)
67+
assert.NilError(t, err)
68+
69+
// have to wait a bit to give time for the command to execute/print
70+
time.Sleep(500 * time.Millisecond)
71+
c.Process.Signal(os.Interrupt)
72+
5173
_ = c.Wait()
5274
assert.Equal(t, c.ProcessState.ExitCode(), 0)
5375
assert.Equal(t, d.String(), "")

0 commit comments

Comments
 (0)