Skip to content

Commit d418e22

Browse files
ianlancetaylorprattmic
authored andcommitted
[release-branch.go1.24] syscall: don't send child signal when testing pidfd
Avoid a spurious SIGCHLD the first time we start a process. For #71828 Fixes #71849 Change-Id: I744100d21bf6aaaaafc99bc5eec9f9f807a50682 Reviewed-on: https://go-review.googlesource.com/c/go/+/651035 Reviewed-by: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Pratt <mpratt@google.com>
1 parent 456eaf5 commit d418e22

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

src/os/exec/exec_posix_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,23 @@ import (
1111
"internal/testenv"
1212
"io"
1313
"os"
14+
"os/exec"
15+
"os/signal"
1416
"os/user"
1517
"path/filepath"
1618
"runtime"
1719
"slices"
1820
"strconv"
1921
"strings"
22+
"sync"
2023
"syscall"
2124
"testing"
2225
"time"
2326
)
2427

2528
func init() {
2629
registerHelperCommand("pwd", cmdPwd)
30+
registerHelperCommand("signaltest", cmdSignalTest)
2731
}
2832

2933
func cmdPwd(...string) {
@@ -274,3 +278,55 @@ func TestExplicitPWD(t *testing.T) {
274278
})
275279
}
276280
}
281+
282+
// Issue 71828.
283+
func TestSIGCHLD(t *testing.T) {
284+
cmd := helperCommand(t, "signaltest")
285+
out, err := cmd.CombinedOutput()
286+
t.Logf("%s", out)
287+
if err != nil {
288+
t.Error(err)
289+
}
290+
}
291+
292+
// cmdSignaltest is for TestSIGCHLD.
293+
// This runs in a separate process because the bug only happened
294+
// the first time that a child process was started.
295+
func cmdSignalTest(...string) {
296+
chSig := make(chan os.Signal, 1)
297+
signal.Notify(chSig, syscall.SIGCHLD)
298+
299+
var wg sync.WaitGroup
300+
wg.Add(1)
301+
go func() {
302+
defer wg.Done()
303+
c := 0
304+
for range chSig {
305+
c++
306+
fmt.Printf("SIGCHLD %d\n", c)
307+
if c > 1 {
308+
fmt.Println("too many SIGCHLD signals")
309+
os.Exit(1)
310+
}
311+
}
312+
}()
313+
defer func() {
314+
signal.Reset(syscall.SIGCHLD)
315+
close(chSig)
316+
wg.Wait()
317+
}()
318+
319+
exe, err := os.Executable()
320+
if err != nil {
321+
fmt.Printf("os.Executable failed: %v\n", err)
322+
os.Exit(1)
323+
}
324+
325+
cmd := exec.Command(exe, "hang", "200ms")
326+
cmd.Stdout = os.Stdout
327+
cmd.Stderr = os.Stderr
328+
if err := cmd.Run(); err != nil {
329+
fmt.Printf("failed to run child process: %v\n", err)
330+
os.Exit(1)
331+
}
332+
}

src/syscall/exec_linux.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ func os_checkClonePidfd() error {
818818
//
819819
//go:noinline
820820
func doCheckClonePidfd(pidfd *int32) (pid uintptr, errno Errno) {
821-
flags := uintptr(CLONE_VFORK | CLONE_VM | CLONE_PIDFD | SIGCHLD)
821+
flags := uintptr(CLONE_VFORK | CLONE_VM | CLONE_PIDFD)
822822
if runtime.GOARCH == "s390x" {
823823
// On Linux/s390, the first two arguments of clone(2) are swapped.
824824
pid, errno = rawVforkSyscall(SYS_CLONE, 0, flags, uintptr(unsafe.Pointer(pidfd)))

0 commit comments

Comments
 (0)