$RodHat_
Syscall reference · Processes

pidfd_send_signal(2)

Send a signal to the process a pidfd refers to, without PID-reuse races.

Since
Linux 5.1check your kernel →
glibc
glibc 2.36
System
Linux
Man page
pidfd_send_signal(2)

Synopsis

#include <linux/signal.h>
#include <signal.h>
#include <sys/syscall.h>
#include <unistd.h>

int syscall(SYS_pidfd_send_signal, int pidfd, int sig,
            siginfo_t *_Nullable info, unsigned int flags);

Rod's take

kill(child, SIGTERM) after the child is gone is how you SIGTERM a stranger. pidfd_send_signal takes the fd, checks the actual task, and hands you ESRCH if your process already exited and got reaped, instead of shooting whoever inherited the number. It landed in 5.1, two releases before pidfd_open, back when you got the fd by opening /proc/<pid>. Pass NULL for info and it behaves like kill(2), which makes the migration close to a one-line diff. No excuse left for signalling by number.

Flags and arguments that matter

NameWhat it does
info = NULLEquivalent to kill(2): the kernel fills in si_signo, si_code = SI_USER, sender PID and UID.
PIDFD_SIGNAL_THREADLinux 6.9Send the signal to the specific thread referenced by pidfd.
PIDFD_SIGNAL_THREAD_GROUPLinux 6.9If pidfd refers to a thread-group leader, signal the whole thread group.
PIDFD_SIGNAL_PROCESS_GROUPLinux 6.9If pidfd refers to a process-group leader, signal the whole process group.

Errors you will actually hit

errnoMeaning
ESRCHThe target process has terminated and been waited on.
EBADFpidfd is not a valid PID file descriptor.
EPERMNo permission to signal the target, or invalid si_code when signalling another process.
EINVALInvalid signal, invalid flags, or caller's PID namespace can't signal the target.

Example

int pfd = syscall(SYS_pidfd_open, pid, 0);
if (pfd < 0)
    err(1, "pidfd_open");

if (syscall(SYS_pidfd_send_signal, pfd, SIGTERM, NULL, 0) < 0) {
    if (errno == ESRCH)
        warnx("already exited and reaped");
    else
        err(1, "pidfd_send_signal");
}
close(pfd);

Trimmed from the full walkthrough in pidfd: Unix finally has a handle on your processes (only took 50 years).

BSD equivalent

FreeBSD: pdkill(2) on a process descriptor from pdfork(2) (FreeBSD 9.0). OpenBSD: none.

The long version, from the console

Sources

  1. pidfd_send_signal(2), man7.org
  2. pdfork(2), FreeBSD
  3. glibc 2.36 NEWS (pidfd_open, pidfd_getfd, pidfd_send_signal added)

Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.