Skip to content

Commit 498ee73

Browse files
Bryan C. Millsgopherbot
Bryan C. Mills
authored andcommitted
os/exec: reduce arbitrary sleeps in TestWaitid
If we use the "pipetest" helper command instead of "sleep", we can use its stdout pipe to determine when the process is ready to handle a SIGSTOP, and we can additionally check that sending a SIGCONT actually causes the process to continue. This also allows us to remove the "sleep" helper command, making the test file somewhat more concise. Noticed while looking into #50138. Change-Id: If4fdee4b1ddf28c6ed07ec3268c81b73c2600238 Reviewed-on: https://go-review.googlesource.com/c/go/+/442576 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Bryan Mills <bcmills@google.com> Auto-Submit: Bryan Mills <bcmills@google.com>
1 parent 379a49c commit 498ee73

File tree

1 file changed

+38
-19
lines changed

1 file changed

+38
-19
lines changed

src/os/exec/exec_posix_test.go

+38-19
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package exec_test
99
import (
1010
"fmt"
1111
"internal/testenv"
12+
"io"
1213
"os"
1314
"os/user"
1415
"path/filepath"
@@ -23,7 +24,6 @@ import (
2324

2425
func init() {
2526
registerHelperCommand("pwd", cmdPwd)
26-
registerHelperCommand("sleep", cmdSleep)
2727
}
2828

2929
func cmdPwd(...string) {
@@ -35,15 +35,6 @@ func cmdPwd(...string) {
3535
fmt.Println(pwd)
3636
}
3737

38-
func cmdSleep(args ...string) {
39-
n, err := strconv.Atoi(args[0])
40-
if err != nil {
41-
fmt.Println(err)
42-
os.Exit(1)
43-
}
44-
time.Sleep(time.Duration(n) * time.Second)
45-
}
46-
4738
func TestCredentialNoSetGroups(t *testing.T) {
4839
if runtime.GOOS == "android" {
4940
maySkipHelperCommand("echo")
@@ -86,15 +77,29 @@ func TestCredentialNoSetGroups(t *testing.T) {
8677
func TestWaitid(t *testing.T) {
8778
t.Parallel()
8879

89-
cmd := helperCommand(t, "sleep", "3")
80+
cmd := helperCommand(t, "pipetest")
81+
stdin, err := cmd.StdinPipe()
82+
if err != nil {
83+
t.Fatal(err)
84+
}
85+
stdout, err := cmd.StdoutPipe()
86+
if err != nil {
87+
t.Fatal(err)
88+
}
9089
if err := cmd.Start(); err != nil {
9190
t.Fatal(err)
9291
}
9392

94-
// The sleeps here are unnecessary in the sense that the test
95-
// should still pass, but they are useful to make it more
96-
// likely that we are testing the expected state of the child.
97-
time.Sleep(100 * time.Millisecond)
93+
// Wait for the child process to come up and register any signal handlers.
94+
const msg = "O:ping\n"
95+
if _, err := io.WriteString(stdin, msg); err != nil {
96+
t.Fatal(err)
97+
}
98+
buf := make([]byte, len(msg))
99+
if _, err := io.ReadFull(stdout, buf); err != nil {
100+
t.Fatal(err)
101+
}
102+
// Now leave the pipes open so that the process will hang until we close stdin.
98103

99104
if err := cmd.Process.Signal(syscall.SIGSTOP); err != nil {
100105
cmd.Process.Kill()
@@ -106,16 +111,30 @@ func TestWaitid(t *testing.T) {
106111
ch <- cmd.Wait()
107112
}()
108113

109-
time.Sleep(100 * time.Millisecond)
114+
// Give a little time for Wait to block on waiting for the process.
115+
// (This is just to give some time to trigger the bug; it should not be
116+
// necessary for the test to pass.)
117+
if testing.Short() {
118+
time.Sleep(1 * time.Millisecond)
119+
} else {
120+
time.Sleep(10 * time.Millisecond)
121+
}
110122

123+
// This call to Signal should succeed because the process still exists.
124+
// (Prior to the fix for #19314, this would fail with os.ErrProcessDone
125+
// or an equivalent error.)
111126
if err := cmd.Process.Signal(syscall.SIGCONT); err != nil {
112127
t.Error(err)
113128
syscall.Kill(cmd.Process.Pid, syscall.SIGCONT)
114129
}
115130

116-
cmd.Process.Kill()
117-
118-
<-ch
131+
// The SIGCONT should allow the process to wake up, notice that stdin
132+
// is closed, and exit successfully.
133+
stdin.Close()
134+
err = <-ch
135+
if err != nil {
136+
t.Fatal(err)
137+
}
119138
}
120139

121140
// https://go.dev/issue/50599: if Env is not set explicitly, setting Dir should

0 commit comments

Comments
 (0)