From a9b59b0215f867c0675d50602208ab8c4f4fe9c7 Mon Sep 17 00:00:00 2001 From: Matt Layher Date: Fri, 18 Mar 2022 09:50:32 -0400 Subject: [PATCH] unix: add PidfdSendSignal on Linux This completes the pidfd_* family of syscalls and adds a test to verify that a child process can be terminated using the new PidfdSendSignal function. Change-Id: I71f6a1e26518f513731e20afef02030462e9a2c0 Reviewed-on: https://go-review.googlesource.com/c/sys/+/393794 Trust: Matt Layher Run-TryBot: Matt Layher TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- unix/linux/types.go | 2 ++ unix/syscall_linux.go | 1 + unix/syscall_linux_test.go | 42 +++++++++++++++++++++++++++++++++++ unix/zsyscall_linux.go | 10 +++++++++ unix/ztypes_linux_386.go | 7 ++++++ unix/ztypes_linux_amd64.go | 8 +++++++ unix/ztypes_linux_arm.go | 7 ++++++ unix/ztypes_linux_arm64.go | 8 +++++++ unix/ztypes_linux_mips.go | 7 ++++++ unix/ztypes_linux_mips64.go | 8 +++++++ unix/ztypes_linux_mips64le.go | 8 +++++++ unix/ztypes_linux_mipsle.go | 7 ++++++ unix/ztypes_linux_ppc.go | 7 ++++++ unix/ztypes_linux_ppc64.go | 8 +++++++ unix/ztypes_linux_ppc64le.go | 8 +++++++ unix/ztypes_linux_riscv64.go | 8 +++++++ unix/ztypes_linux_s390x.go | 8 +++++++ unix/ztypes_linux_sparc64.go | 8 +++++++ 18 files changed, 162 insertions(+) diff --git a/unix/linux/types.go b/unix/linux/types.go index f9b6c46d..d563a0cf 100644 --- a/unix/linux/types.go +++ b/unix/linux/types.go @@ -934,6 +934,8 @@ const _C__NSIG = C._NSIG type SignalfdSiginfo C.struct_signalfd_siginfo +type Siginfo C.siginfo_t + // Terminal handling type Termios C.termios_t diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go index d7a94e76..2a6affed 100644 --- a/unix/syscall_linux.go +++ b/unix/syscall_linux.go @@ -2297,6 +2297,7 @@ type RemoteIovec struct { //sys PidfdOpen(pid int, flags int) (fd int, err error) = SYS_PIDFD_OPEN //sys PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) = SYS_PIDFD_GETFD +//sys PidfdSendSignal(pidfd int, sig Signal, info *Siginfo, flags int) (err error) = SYS_PIDFD_SEND_SIGNAL //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) //sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go index 67b2f5de..cab25501 100644 --- a/unix/syscall_linux_test.go +++ b/unix/syscall_linux_test.go @@ -15,11 +15,13 @@ import ( "io/ioutil" "net" "os" + "os/exec" "path/filepath" "runtime" "runtime/debug" "strconv" "strings" + "syscall" "testing" "time" "unsafe" @@ -217,6 +219,46 @@ func firstIPv4(t *testing.T, ifi *net.Interface) (net.IP, bool) { return nil, false } +func TestPidfd(t *testing.T) { + // Start a child process which will sleep for 1 hour; longer than the 10 + // minute default Go test timeout. + cmd := exec.Command("sleep", "1h") + if err := cmd.Start(); err != nil { + t.Fatalf("failed to exec sleep: %v", err) + } + + fd, err := unix.PidfdOpen(cmd.Process.Pid, 0) + if err != nil { + // GOARCH arm/arm64 and GOOS android builders do not support pidfds. + if errors.Is(err, unix.ENOSYS) { + t.Skipf("skipping, pidfd_open is not implemented: %v", err) + } + + t.Fatalf("failed to open child pidfd: %v", err) + } + defer unix.Close(fd) + + const want = unix.SIGHUP + if err := unix.PidfdSendSignal(fd, want, nil, 0); err != nil { + t.Fatalf("failed to signal child process: %v", err) + } + + // Now verify that the child process received the expected signal. + var eerr *exec.ExitError + if err := cmd.Wait(); !errors.As(err, &eerr) { + t.Fatalf("child process terminated but did not return an exit error: %v", err) + } + + ws, ok := eerr.Sys().(syscall.WaitStatus) + if !ok { + t.Fatalf("expected syscall.WaitStatus value, but got: %#T", eerr.Sys()) + } + + if got := ws.Signal(); got != want { + t.Fatalf("unexpected child exit signal, got: %s, want: %s", got, want) + } +} + func TestPpoll(t *testing.T) { if runtime.GOOS == "android" { t.Skip("mkfifo syscall is not available on android, skipping test") diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go index 30fa4055..e5299395 100644 --- a/unix/zsyscall_linux.go +++ b/unix/zsyscall_linux.go @@ -1992,6 +1992,16 @@ func PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func PidfdSendSignal(pidfd int, sig Signal, info *Siginfo, flags int) (err error) { + _, _, e1 := Syscall6(SYS_PIDFD_SEND_SIGNAL, uintptr(pidfd), uintptr(sig), uintptr(unsafe.Pointer(info)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { r0, _, e1 := Syscall(SYS_SHMAT, uintptr(id), uintptr(addr), uintptr(flag)) ret = uintptr(r0) diff --git a/unix/ztypes_linux_386.go b/unix/ztypes_linux_386.go index bea25494..531aefab 100644 --- a/unix/ztypes_linux_386.go +++ b/unix/ztypes_linux_386.go @@ -250,6 +250,13 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ [116]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_amd64.go b/unix/ztypes_linux_amd64.go index b8c8f289..727f664b 100644 --- a/unix/ztypes_linux_amd64.go +++ b/unix/ztypes_linux_amd64.go @@ -265,6 +265,14 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_arm.go b/unix/ztypes_linux_arm.go index 4db44301..639141b1 100644 --- a/unix/ztypes_linux_arm.go +++ b/unix/ztypes_linux_arm.go @@ -241,6 +241,13 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ [116]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_arm64.go b/unix/ztypes_linux_arm64.go index 3ebcad8a..6cb03b1d 100644 --- a/unix/ztypes_linux_arm64.go +++ b/unix/ztypes_linux_arm64.go @@ -244,6 +244,14 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_mips.go b/unix/ztypes_linux_mips.go index 3eb33e48..4a155545 100644 --- a/unix/ztypes_linux_mips.go +++ b/unix/ztypes_linux_mips.go @@ -246,6 +246,13 @@ type Sigset_t struct { const _C__NSIG = 0x80 +type Siginfo struct { + Signo int32 + Code int32 + Errno int32 + _ [116]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_mips64.go b/unix/ztypes_linux_mips64.go index 79a94467..e1084926 100644 --- a/unix/ztypes_linux_mips64.go +++ b/unix/ztypes_linux_mips64.go @@ -247,6 +247,14 @@ type Sigset_t struct { const _C__NSIG = 0x80 +type Siginfo struct { + Signo int32 + Code int32 + Errno int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_mips64le.go b/unix/ztypes_linux_mips64le.go index 8f4b107c..8904ac84 100644 --- a/unix/ztypes_linux_mips64le.go +++ b/unix/ztypes_linux_mips64le.go @@ -247,6 +247,14 @@ type Sigset_t struct { const _C__NSIG = 0x80 +type Siginfo struct { + Signo int32 + Code int32 + Errno int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_mipsle.go b/unix/ztypes_linux_mipsle.go index e4eb2179..a1a28cc7 100644 --- a/unix/ztypes_linux_mipsle.go +++ b/unix/ztypes_linux_mipsle.go @@ -246,6 +246,13 @@ type Sigset_t struct { const _C__NSIG = 0x80 +type Siginfo struct { + Signo int32 + Code int32 + Errno int32 + _ [116]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_ppc.go b/unix/ztypes_linux_ppc.go index d5b21f0f..abdc5345 100644 --- a/unix/ztypes_linux_ppc.go +++ b/unix/ztypes_linux_ppc.go @@ -253,6 +253,13 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ [116]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_ppc64.go b/unix/ztypes_linux_ppc64.go index 5188d142..f4afbbe0 100644 --- a/unix/ztypes_linux_ppc64.go +++ b/unix/ztypes_linux_ppc64.go @@ -254,6 +254,14 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_ppc64le.go b/unix/ztypes_linux_ppc64le.go index de4dd4c7..ea0b8406 100644 --- a/unix/ztypes_linux_ppc64le.go +++ b/unix/ztypes_linux_ppc64le.go @@ -254,6 +254,14 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_riscv64.go b/unix/ztypes_linux_riscv64.go index dccbf9b0..85d0a0d5 100644 --- a/unix/ztypes_linux_riscv64.go +++ b/unix/ztypes_linux_riscv64.go @@ -272,6 +272,14 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_s390x.go b/unix/ztypes_linux_s390x.go index c426c357..81dd9c22 100644 --- a/unix/ztypes_linux_s390x.go +++ b/unix/ztypes_linux_s390x.go @@ -267,6 +267,14 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/unix/ztypes_linux_sparc64.go b/unix/ztypes_linux_sparc64.go index 765edc13..6991b00b 100644 --- a/unix/ztypes_linux_sparc64.go +++ b/unix/ztypes_linux_sparc64.go @@ -249,6 +249,14 @@ type Sigset_t struct { const _C__NSIG = 0x41 +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32