Skip to content

Commit

Permalink
os/exec: in TestContextCancel, dump goroutines on failure
Browse files Browse the repository at this point in the history
If this test fails, we want to know exactly what the os/exec
goroutines are doing. Panicking gives us a goroutine dump,
whereas t.Fatal does not.

While we're here, use exponential backoff instead of a hard-coded 1ms
sleep. We want to give the OS enough time to actually terminate the
subprocess.

For #42061

Change-Id: I3d50a71ac314853c68a935218e7f97ce18b08b5b
Reviewed-on: https://go-review.googlesource.com/c/go/+/368317
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
Bryan C. Mills committed Dec 2, 2021
1 parent c3a7fb2 commit 00dbcb3
Showing 1 changed file with 17 additions and 2 deletions.
19 changes: 17 additions & 2 deletions src/os/exec/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,10 @@ func TestContext(t *testing.T) {
}

func TestContextCancel(t *testing.T) {
// To reduce noise in the final goroutine dump,
// let other parallel tests complete if possible.
t.Parallel()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := helperCommandContext(t, ctx, "cat")
Expand All @@ -978,14 +982,25 @@ func TestContextCancel(t *testing.T) {
// Calling cancel should have killed the process, so writes
// should now fail. Give the process a little while to die.
start := time.Now()
delay := 1 * time.Millisecond
for {
if _, err := io.WriteString(stdin, "echo"); err != nil {
break
}

if time.Since(start) > time.Minute {
t.Fatal("canceling context did not stop program")
// Panic instead of calling t.Fatal so that we get a goroutine dump.
// We want to know exactly what the os/exec goroutines got stuck on.
panic("canceling context did not stop program")
}

// Back off exponentially (up to 1-second sleeps) to give the OS time to
// terminate the process.
delay *= 2
if delay > 1*time.Second {
delay = 1 * time.Second
}
time.Sleep(time.Millisecond)
time.Sleep(delay)
}

if err := c.Wait(); err == nil {
Expand Down

0 comments on commit 00dbcb3

Please sign in to comment.