diff options
Diffstat (limited to 'man2/pidfd_open.2')
-rw-r--r-- | man2/pidfd_open.2 | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/man2/pidfd_open.2 b/man2/pidfd_open.2 new file mode 100644 index 0000000..8321e82 --- /dev/null +++ b/man2/pidfd_open.2 @@ -0,0 +1,269 @@ +.\" Copyright (c) 2019 by Michael Kerrisk <mtk.manpages@gmail.com> +.\" +.\" SPDX-License-Identifier: Linux-man-pages-copyleft +.\" +.TH pidfd_open 2 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +pidfd_open \- obtain a file descriptor that refers to a process +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.BR "#include <sys/syscall.h>" " /* Definition of " SYS_* " constants */" +.B #include <unistd.h> +.PP +.BI "int syscall(SYS_pidfd_open, pid_t " pid ", unsigned int " flags ); +.fi +.PP +.IR Note : +glibc provides no wrapper for +.BR pidfd_open (), +necessitating the use of +.BR syscall (2). +.SH DESCRIPTION +The +.BR pidfd_open () +system call creates a file descriptor that refers to +the process whose PID is specified in +.IR pid . +The file descriptor is returned as the function result; +the close-on-exec flag is set on the file descriptor. +.PP +The +.I flags +argument either has the value 0, or contains the following flag: +.TP +.BR PIDFD_NONBLOCK " (since Linux 5.10)" +.\" commit 4da9af0014b51c8b015ed8c622440ef28912efe6 +Return a nonblocking file descriptor. +If the process referred to by the file descriptor has not yet terminated, +then an attempt to wait on the file descriptor using +.BR waitid (2) +will immediately return the error +.B EAGAIN +rather than blocking. +.SH RETURN VALUE +On success, +.BR pidfd_open () +returns a file descriptor (a nonnegative integer). +On error, \-1 is returned and +.I errno +is set to indicate the error. +.SH ERRORS +.TP +.B EINVAL +.I flags +is not valid. +.TP +.B EINVAL +.I pid +is not valid. +.TP +.B EMFILE +The per-process limit on the number of open file descriptors has been reached +(see the description of +.B RLIMIT_NOFILE +in +.BR getrlimit (2)). +.TP +.B ENFILE +The system-wide limit on the total number of open files has been reached. +.TP +.B ENODEV +The anonymous inode filesystem is not available in this kernel. +.TP +.B ENOMEM +Insufficient kernel memory was available. +.TP +.B ESRCH +The process specified by +.I pid +does not exist. +.SH STANDARDS +Linux. +.SH HISTORY +Linux 5.3. +.SH NOTES +The following code sequence can be used to obtain a file descriptor +for the child of +.BR fork (2): +.PP +.in +4n +.EX +pid = fork(); +if (pid > 0) { /* If parent */ + pidfd = pidfd_open(pid, 0); + ... +} +.EE +.in +.PP +Even if the child has already terminated by the time of the +.BR pidfd_open () +call, its PID will not have been recycled and the returned +file descriptor will refer to the resulting zombie process. +Note, however, that this is guaranteed only if the following +conditions hold true: +.IP \[bu] 3 +the disposition of +.B SIGCHLD +has not been explicitly set to +.B SIG_IGN +(see +.BR sigaction (2)); +.IP \[bu] +the +.B SA_NOCLDWAIT +flag was not specified while establishing a handler for +.B SIGCHLD +or while setting the disposition of that signal to +.B SIG_DFL +(see +.BR sigaction (2)); +and +.IP \[bu] +the zombie process was not reaped elsewhere in the program +(e.g., either by an asynchronously executed signal handler or by +.BR wait (2) +or similar in another thread). +.PP +If any of these conditions does not hold, +then the child process (along with a PID file descriptor that refers to it) +should instead be created using +.BR clone (2) +with the +.B CLONE_PIDFD +flag. +.\" +.SS Use cases for PID file descriptors +A PID file descriptor returned by +.BR pidfd_open () +(or by +.BR clone (2) +with the +.B CLONE_PID +flag) can be used for the following purposes: +.IP \[bu] 3 +The +.BR pidfd_send_signal (2) +system call can be used to send a signal to the process referred to by +a PID file descriptor. +.IP \[bu] +A PID file descriptor can be monitored using +.BR poll (2), +.BR select (2), +and +.BR epoll (7). +When the process that it refers to terminates, +these interfaces indicate the file descriptor as readable. +Note, however, that in the current implementation, +nothing can be read from the file descriptor +.RB ( read (2) +on the file descriptor fails with the error +.BR EINVAL ). +.IP \[bu] +If the PID file descriptor refers to a child of the calling process, +then it can be waited on using +.BR waitid (2). +.IP \[bu] +The +.BR pidfd_getfd (2) +system call can be used to obtain a duplicate of a file descriptor +of another process referred to by a PID file descriptor. +.IP \[bu] +A PID file descriptor can be used as the argument of +.BR setns (2) +in order to move into one or more of the same namespaces as the process +referred to by the file descriptor. +.IP \[bu] +A PID file descriptor can be used as the argument of +.BR process_madvise (2) +in order to provide advice on the memory usage patterns of the process +referred to by the file descriptor. +.PP +The +.BR pidfd_open () +system call is the preferred way of obtaining a PID file descriptor +for an already existing process. +The alternative is to obtain a file descriptor by opening a +.IR /proc/ pid +directory. +However, the latter technique is possible only if the +.BR proc (5) +filesystem is mounted; +furthermore, the file descriptor obtained in this way is +.I not +pollable and can't be waited on with +.BR waitid (2). +.SH EXAMPLES +The program below opens a PID file descriptor for the +process whose PID is specified as its command-line argument. +It then uses +.BR poll (2) +to monitor the file descriptor for process exit, as indicated by an +.B EPOLLIN +event. +.\" +.SS Program source +\& +.\" SRC BEGIN (pidfd_open.c) +.EX +#define _GNU_SOURCE +#include <poll.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/syscall.h> +#include <unistd.h> +\& +static int +pidfd_open(pid_t pid, unsigned int flags) +{ + return syscall(SYS_pidfd_open, pid, flags); +} +\& +int +main(int argc, char *argv[]) +{ + int pidfd, ready; + struct pollfd pollfd; +\& + if (argc != 2) { + fprintf(stderr, "Usage: %s <pid>\en", argv[0]); + exit(EXIT_SUCCESS); + } +\& + pidfd = pidfd_open(atoi(argv[1]), 0); + if (pidfd == \-1) { + perror("pidfd_open"); + exit(EXIT_FAILURE); + } +\& + pollfd.fd = pidfd; + pollfd.events = POLLIN; +\& + ready = poll(&pollfd, 1, \-1); + if (ready == \-1) { + perror("poll"); + exit(EXIT_FAILURE); + } +\& + printf("Events (%#x): POLLIN is %sset\en", pollfd.revents, + (pollfd.revents & POLLIN) ? "" : "not "); +\& + close(pidfd); + exit(EXIT_SUCCESS); +} +.EE +.\" SRC END +.SH SEE ALSO +.BR clone (2), +.BR kill (2), +.BR pidfd_getfd (2), +.BR pidfd_send_signal (2), +.BR poll (2), +.BR process_madvise (2), +.BR select (2), +.BR setns (2), +.BR waitid (2), +.BR epoll (7) |