From: Tobias Klauser Date: Tue, 19 Nov 2024 12:38:42 +0000 (+0100) Subject: internal/syscall/unix, os: add and use Waitid syscall wrapper on linux X-Git-Tag: go1.24rc1~245 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e82308c198fbc26800fd1780cbd9f29935b210c5;p=gostls13.git internal/syscall/unix, os: add and use Waitid syscall wrapper on linux Instead of open-coding the waitid syscall wrapper add it to internal/syscall/unix. As the syscall is currently only used on Linux, switch the implementation in os.(*Process).blockUntilWaitable to use the 128-byte unix.SiginfoChild type instead of a plain 128-byte buffer. Also use ignoringEINTR for the waitid calls instead of open-coding it. Change-Id: I8dc47e361faa1f5e912d5de021f119c91c9f12f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/629655 Reviewed-by: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Auto-Submit: Tobias Klauser --- diff --git a/src/internal/syscall/unix/waitid_linux.go b/src/internal/syscall/unix/waitid_linux.go new file mode 100644 index 0000000000..240a7f744c --- /dev/null +++ b/src/internal/syscall/unix/waitid_linux.go @@ -0,0 +1,23 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +import ( + "syscall" + "unsafe" +) + +const ( + P_PID = 1 + P_PIDFD = 3 +) + +func Waitid(idType int, id int, info *SiginfoChild, options int, rusage *syscall.Rusage) error { + _, _, errno := syscall.Syscall6(syscall.SYS_WAITID, uintptr(idType), uintptr(id), uintptr(unsafe.Pointer(info)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0) + if errno != 0 { + return errno + } + return nil +} diff --git a/src/os/pidfd_linux.go b/src/os/pidfd_linux.go index 0bfef7759c..fe4a743cf8 100644 --- a/src/os/pidfd_linux.go +++ b/src/os/pidfd_linux.go @@ -21,7 +21,7 @@ import ( "runtime" "sync" "syscall" - "unsafe" + _ "unsafe" // for linkname ) // ensurePidfd initializes the PidFD field in sysAttr if it is not already set. @@ -78,9 +78,6 @@ func pidfdFind(pid int) (uintptr, error) { return h, nil } -// _P_PIDFD is used as idtype argument to waitid syscall. -const _P_PIDFD = 3 - func (p *Process) pidfdWait() (*ProcessState, error) { // When pidfd is used, there is no wait/kill race (described in CL 23967) // because the PID recycle issue doesn't exist (IOW, pidfd, unlike PID, @@ -104,16 +101,12 @@ func (p *Process) pidfdWait() (*ProcessState, error) { var ( info unix.SiginfoChild rusage syscall.Rusage - e syscall.Errno ) - for { - _, _, e = syscall.Syscall6(syscall.SYS_WAITID, _P_PIDFD, handle, uintptr(unsafe.Pointer(&info)), syscall.WEXITED, uintptr(unsafe.Pointer(&rusage)), 0) - if e != syscall.EINTR { - break - } - } - if e != 0 { - return nil, NewSyscallError("waitid", e) + err := ignoringEINTR(func() error { + return unix.Waitid(unix.P_PIDFD, int(handle), &info, syscall.WEXITED, &rusage) + }) + if err != nil { + return nil, NewSyscallError("waitid", err) } // Release the Process' handle reference, in addition to the reference // we took above. @@ -168,12 +161,9 @@ func checkPidfd() error { defer syscall.Close(int(fd)) // Check waitid(P_PIDFD) works. - for { - _, _, err = syscall.Syscall6(syscall.SYS_WAITID, _P_PIDFD, fd, 0, syscall.WEXITED, 0, 0) - if err != syscall.EINTR { - break - } - } + err = ignoringEINTR(func() error { + return unix.Waitid(unix.P_PIDFD, int(fd), nil, syscall.WEXITED, nil) + }) // Expect ECHILD from waitid since we're not our own parent. if err != syscall.ECHILD { return NewSyscallError("pidfd_wait", err) diff --git a/src/os/wait_waitid.go b/src/os/wait_waitid.go index f2447a0e4c..832dbe907b 100644 --- a/src/os/wait_waitid.go +++ b/src/os/wait_waitid.go @@ -10,29 +10,18 @@ package os import ( + "internal/syscall/unix" "runtime" "syscall" - "unsafe" ) -const _P_PID = 1 - // blockUntilWaitable attempts to block until a call to p.Wait will // succeed immediately, and reports whether it has done so. // It does not actually call p.Wait. func (p *Process) blockUntilWaitable() (bool, error) { - // The waitid system call expects a pointer to a siginfo_t, - // which is 128 bytes on all Linux systems. - // On darwin/amd64, it requires 104 bytes. - // We don't care about the values it returns. - var siginfo [16]uint64 - psig := &siginfo[0] + var info unix.SiginfoChild err := ignoringEINTR(func() error { - _, _, errno := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(p.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0) - if errno != 0 { - return errno - } - return nil + return unix.Waitid(unix.P_PID, p.Pid, &info, syscall.WEXITED|syscall.WNOWAIT, nil) }) runtime.KeepAlive(p) if err != nil {