From 36772127a21fa5a8ea615746594d2f22f7d1607e Mon Sep 17 00:00:00 2001 From: Matt Layher Date: Fri, 25 Mar 2022 15:27:30 -0400 Subject: [PATCH] unix: implement Waitid on Linux waitid(2) can be used to wait on pidfds. Update TestPidfd to test this new functionality as well. Change-Id: I5f26140b9afd5a6ec3f04217fb1c91542936a2c3 Reviewed-on: https://go-review.googlesource.com/c/sys/+/395936 Trust: Matt Layher Run-TryBot: Matt Layher TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser --- unix/mkerrors.sh | 1 + unix/syscall_linux.go | 3 ++- unix/syscall_linux_test.go | 9 +++++++++ unix/zerrors_linux.go | 4 ++++ unix/zsyscall_linux.go | 10 ++++++++++ 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh index a0370874..72f65a9a 100755 --- a/unix/mkerrors.sh +++ b/unix/mkerrors.sh @@ -603,6 +603,7 @@ ccflags="$@" $2 ~ /^ITIMER_/ || $2 !~ "WMESGLEN" && $2 ~ /^W[A-Z0-9]+$/ || + $2 ~ /^P_/ || $2 ~/^PPPIOC/ || $2 ~ /^FAN_|FANOTIFY_/ || $2 == "HID_MAX_DESCRIPTOR_SIZE" || diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go index 2a6affed..bda98498 100644 --- a/unix/syscall_linux.go +++ b/unix/syscall_linux.go @@ -366,6 +366,8 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, return } +//sys Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) + func Mkfifo(path string, mode uint32) error { return Mknod(path, mode|S_IFIFO, 0) } @@ -2446,5 +2448,4 @@ func Setitimer(which ItimerWhich, it Itimerval) (Itimerval, error) { // Vfork // Vhangup // Vserver -// Waitid // _Sysctl diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go index cab25501..e20c767d 100644 --- a/unix/syscall_linux_test.go +++ b/unix/syscall_linux_test.go @@ -238,6 +238,11 @@ func TestPidfd(t *testing.T) { } defer unix.Close(fd) + // Child is running but not terminated. + if err := unix.Waitid(unix.P_PIDFD, fd, nil, unix.WEXITED|unix.WNOHANG, nil); err != nil { + t.Fatalf("failed to check for child exit: %v", err) + } + const want = unix.SIGHUP if err := unix.PidfdSendSignal(fd, want, nil, 0); err != nil { t.Fatalf("failed to signal child process: %v", err) @@ -249,6 +254,10 @@ func TestPidfd(t *testing.T) { t.Fatalf("child process terminated but did not return an exit error: %v", err) } + if err := unix.Waitid(unix.P_PIDFD, fd, nil, unix.WEXITED, nil); !errors.Is(err, unix.ECHILD) { + t.Fatalf("expected ECHILD for final waitid, but got: %v", err) + } + ws, ok := eerr.Sys().(syscall.WaitStatus) if !ok { t.Fatalf("expected syscall.WaitStatus value, but got: %#T", eerr.Sys()) diff --git a/unix/zerrors_linux.go b/unix/zerrors_linux.go index bc7c9d07..36a89c64 100644 --- a/unix/zerrors_linux.go +++ b/unix/zerrors_linux.go @@ -2135,6 +2135,10 @@ const ( PTRACE_SYSCALL_INFO_NONE = 0x0 PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 + P_ALL = 0x0 + P_PGID = 0x2 + P_PID = 0x1 + P_PIDFD = 0x3 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 RAMFS_MAGIC = 0x858458f6 diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go index e5299395..78d74520 100644 --- a/unix/zsyscall_linux.go +++ b/unix/zsyscall_linux.go @@ -231,6 +231,16 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) { + _, _, e1 := Syscall6(SYS_WAITID, uintptr(idType), uintptr(id), uintptr(unsafe.Pointer(info)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func KeyctlInt(cmd int, arg2 int, arg3 int, arg4 int, arg5 int) (ret int, err error) { r0, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5), 0) ret = int(r0)