--- /dev/null
+// 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
+}
"runtime"
"sync"
"syscall"
- "unsafe"
+ _ "unsafe" // for linkname
)
// ensurePidfd initializes the PidFD field in sysAttr if it is not already set.
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,
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.
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)
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 {