]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.23] syscall: don't send child signal when testing pidfd
authorIan Lance Taylor <iant@golang.org>
Thu, 20 Feb 2025 01:37:49 +0000 (17:37 -0800)
committerMichael Pratt <mpratt@google.com>
Wed, 26 Feb 2025 17:45:28 +0000 (09:45 -0800)
Avoid a spurious SIGCHLD the first time we start a process.

For #71828
Fixes #71848

Change-Id: I744100d21bf6aaaaafc99bc5eec9f9f807a50682
Reviewed-on: https://go-review.googlesource.com/c/go/+/651055
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/os/exec/exec_posix_test.go
src/syscall/exec_linux.go

index 5d828b3475a40a0cd7dcfee5e00da4d15a193190..7c77bfa712559d0d70628cdf18ccd3ced7d8b3b5 100644 (file)
@@ -11,12 +11,15 @@ import (
        "internal/testenv"
        "io"
        "os"
+       "os/exec"
+       "os/signal"
        "os/user"
        "path/filepath"
        "reflect"
        "runtime"
        "strconv"
        "strings"
+       "sync"
        "syscall"
        "testing"
        "time"
@@ -24,6 +27,7 @@ import (
 
 func init() {
        registerHelperCommand("pwd", cmdPwd)
+       registerHelperCommand("signaltest", cmdSignalTest)
 }
 
 func cmdPwd(...string) {
@@ -274,3 +278,55 @@ func TestExplicitPWD(t *testing.T) {
                })
        }
 }
+
+// Issue 71828.
+func TestSIGCHLD(t *testing.T) {
+       cmd := helperCommand(t, "signaltest")
+       out, err := cmd.CombinedOutput()
+       t.Logf("%s", out)
+       if err != nil {
+               t.Error(err)
+       }
+}
+
+// cmdSignaltest is for TestSIGCHLD.
+// This runs in a separate process because the bug only happened
+// the first time that a child process was started.
+func cmdSignalTest(...string) {
+       chSig := make(chan os.Signal, 1)
+       signal.Notify(chSig, syscall.SIGCHLD)
+
+       var wg sync.WaitGroup
+       wg.Add(1)
+       go func() {
+               defer wg.Done()
+               c := 0
+               for range chSig {
+                       c++
+                       fmt.Printf("SIGCHLD %d\n", c)
+                       if c > 1 {
+                               fmt.Println("too many SIGCHLD signals")
+                               os.Exit(1)
+                       }
+               }
+       }()
+       defer func() {
+               signal.Reset(syscall.SIGCHLD)
+               close(chSig)
+               wg.Wait()
+       }()
+
+       exe, err := os.Executable()
+       if err != nil {
+               fmt.Printf("os.Executable failed: %v\n", err)
+               os.Exit(1)
+       }
+
+       cmd := exec.Command(exe, "hang", "200ms")
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = os.Stderr
+       if err := cmd.Run(); err != nil {
+               fmt.Printf("failed to run child process: %v\n", err)
+               os.Exit(1)
+       }
+}
index dfd9a8368a9e50b2f27e242f9e5f18e72e5cb893..e8ba342954e1b685f2cb4704e270d4af1752a5e7 100644 (file)
@@ -803,7 +803,7 @@ func os_checkClonePidfd() error {
 //
 //go:noinline
 func doCheckClonePidfd(pidfd *int32) (pid uintptr, errno Errno) {
-       flags := uintptr(CLONE_VFORK|CLONE_VM|CLONE_PIDFD|SIGCHLD)
+       flags := uintptr(CLONE_VFORK | CLONE_VM | CLONE_PIDFD)
        if runtime.GOARCH == "s390x" {
                // On Linux/s390, the first two arguments of clone(2) are swapped.
                pid, errno = rawVforkSyscall(SYS_CLONE, 0, flags, uintptr(unsafe.Pointer(pidfd)))