PDFORK(2) System Calls Manual PDFORK(2) NAME pdfork, pdrfork, pdopenpid, pdgetpid, pdkill, pdwait, pddupfd -- System calls to manage process descriptors LIBRARY Standard C Library (libc, -lc) SYNOPSIS #include <sys/procdesc.h> pid_t pdfork(int *fdp, int pdflags); pid_t pdrfork(int *fdp, int pdflags, int rfflags); int pdopenpid(pid_t pid, int pdflags); int pdgetpid(int fd, pid_t *pidp); int pdkill(int fd, int signum); int pdwait(int fd, int *status, int options, struct __wrusage *wrusage, struct __siginfo *info); int pddupfd(int fd, int remotefd, int flags); int pdptrace(int req, int fd, int lwpid, void *addr, int data); DESCRIPTION Process descriptors are special file descriptors that represent processes, and are created using pdfork(), a variant of fork(2), which, if successful, returns a process descriptor in the integer pointed to by fdp. Processes created via pdfork() will not cause SIGCHLD on termination. pdfork() can accept the pdflags: PD_DAEMON Instead of the default terminate-on-close behaviour, allow the process to live until it is explicitly killed with kill(2). This option is not permitted in capsicum(4) capability mode (see cap_enter(2)). Note: the option changes the behavior of close(2) for the process descriptor returned by the operation. If there is another process descriptor for the same process, created without specifying the PD_DAEMON flag, closing that descrip- tor kills the process. PD_CLOEXEC Set close-on-exec on process descriptor. PD_NOWAITPID The parent cannot obtain the child's status with waitpid(2). PD_PTRACE_CAP Enable pdptrace(2) requests on the resulting file descrip- tor. Otherwise the descriptor cannot be used to debug the child process. See rights(4) for the description of the CAP_PTRACE capability. The pdrfork() system call is a variant of pdfork() that also takes the rfflags argument to control sharing of process resources between the caller and the new process. Like pdfork(), the function writes the process de- scriptor referencing the created process into the location pointed to by the fdp argument. See rfork(2) for a description of the possible rfflag flags. The pdrfork() system call requires that both the RFPROC and RFPROCDESC flags, or RFSPAWN flag are specified. The pdopenpid() function opens the process descriptor for the process spec- ified by the argument pid. It takes the same flags in the pdflags argument as pdfork(). The caller must have permission to debug the target process in order for pdopenpid() to succeed. Zombie processes cannot be opened. There might be more that one file descriptor referencing the process. Af- ter the zombie is reaped, calls to pdwait() specifying any file descriptors for the same process fail with the ESRCH error. The pdopenpid() system call is allowed in the capability mode (see cap- sicum(4)) when the target process is the child of the calling process, or when the calling process is the debugger of the target process. The debug- ger is attached to its target by ptrace(2), pdptrace(2), or by other means, e.g., by debugging the target process' parent with the follow-on-fork mode enabled. pdgetpid() queries the process ID (PID) in the process descriptor fd. pdkill() is functionally identical to kill(2), except that it accepts a process descriptor, fd, rather than a PID. The pdwait() system call allows the calling thread to wait and retrieve the status information on the process referenced by the fd process descriptor. See the description of the wait6(2) system call for the behavior specifica- tion. The pddupfd() function allows the caller to duplicate a file descriptor across the process boundaries. The function returns the new file descrip- tor that points to the same file as the file descriptor remotefd in the process specified by the fd process descriptor. The returned file descrip- tor has the O_CLOEXEC flag set. The flags argument is reserved and must be zero. Certain file descriptor types cannot be copied this way, namely kqueues. The pdptrace() function enables execution of ptrace(2) requests on the process specified by the process descriptor fd. In addition to the arguments taken by the ptrace(2), system call, the lwpid thread identifier can designate the thread on which the request must oper- ate. The lwpid argument can be specified as -1 if the call is not thread- specific, or kernel is allowed to select some thread on its own. Unlike the ptrace(2) implementation, pdptrace() does not clear the errno variable before executing the system call. INTERACTION OF PROCESS DESCRIPTORS AND WAITPID(2) The pdwait() system call may be called on a process descriptor an unlimited number of times. In particular, it does not reap the target process, even if that process has exited. Each time, it returns the same status. - If the process was forked with pdfork(), and the PD_NOWAITPID flag was specified, then the process is automatically reaped after the last process descriptor referencing that process is closed. No waitpid(2) call (or a call from the same family of the wait functions which operate on PIDs) are needed to reap the zombie process. - If the process was created by pdfork(), and the PD_NOWAITPID flag was not specified, then after exiting, the process will not be reaped until the parent or reaper has called waitpid(2) and all process descriptors referencing the process are closed. - If the process was created by the fork(2) system call (which does not allocate a process descriptor for the child), and later the process was opened by pdopenpid(), then a waitpid(2) call from the parent is needed to reap the exited child. In any case, the PID of the process is not reused until its zombie is reaped, and all its process descriptors are closed. A debugger attached by ptrace(2) can execute the waitpid() calls against the alive target regardless of the way the target process was forked. INTERACTION OF PROCESS DESCRIPTORS WITH OTHER SYSTEM CALLS The following system calls also have effects specific to process descrip- tors: fstat(2) queries status of a process descriptor; currently only the st_mode, st_birthtime, st_atime, st_ctime and st_mtime fields are defined. If the owner read, write, and execute bits are set then the process repre- sented by the process descriptor is still alive. poll(2) and select(2) allow waiting for process state transitions; cur- rently only POLLHUP is defined, and will be raised when the process dies. Process state transitions can also be monitored using kqueue(2) filter EVFILT_PROCDESC; currently only NOTE_EXIT is implemented. close(2) will close the process descriptor unless PD_DAEMON is set; if the process is still alive and this is the last reference to the process de- scriptor, the process will be terminated with the signal SIGKILL. The PID of the referenced process is not reused until the process descriptor is closed, whether or not the zombie process is reaped by pdwait(), wait6, or similar system calls. RETURN VALUES pdfork() and pdrfork() return a PID, 0 or -1, as fork(2) does. pdopenpid(), pdgetpid(), pdkill(), pdwait(), and pddupfd() return 0 on suc- cess and -1 on failure. ERRORS These functions may return the same error numbers as their PID-based equiv- alents (e.g. pdfork() may return the same error numbers as fork(2)), with the following additions: [EFAULT] The copyout of the resulting file descriptor value to the memory pointed to by fdp failed. Note that the child process was already created when this condition is detected, and the child continues exe- cution, same as the parent. If this error must be han- dled, it is advisable to memoize the getpid() result be- fore the call to pdfork() or pdrfork(), and compare it to the value returned by getpid() after, to see if code is executing in parent or child. [EINVAL] The signal number given to pdkill() is invalid. [ENOTCAPABLE] The process descriptor being operated on has insuffi- cient rights (e.g. CAP_PDKILL for pdkill()). [EINVAL] The pdwait() function is called with reserved bits set in options. The pdopenpid() might return the same errors as open(2), related to the file descriptor allocation problems, as well as the following specific er- rors: [EINVAL] The flags argument has reserved bits set. [ECAPMODE] pdopenpid() is called by the process in capability mode. [EBUSY] The process specified by the pid argument already termi- nated. [ESRCH] The process specified by the pid argument does not ex- ist, or the caller does not have enough privileges to open the process. [EMFILE] The calling process already reached its limit for open file descriptors. Current implementation installs the opened process de- scriptor into the calling process's file descriptors ta- ble. If the descriptor cannot be installed, the process descriptor is closed, which executes all actions per- formed by close(2) on it. The pddupfd() returns the following errors: [EINVAL] The flags argument is not zero. [EINVAL] The file descriptor fd is not a process file descriptor. [ESRCH] The process specified by the file descriptor fd exited. [EBADF] The file descriptor remotefd is not a valid file de- scriptor in the specified process. [ENOENT] The specified process does not have a file descriptor table. [EOPNOTSUPP] remotefd refers to a file that cannot be duplicated across a process boundary, such as a kqueue. The pdptrace() system call returns the same errors as ptrace(2), as well as the following specific errors: [ECAPMODE] The process issuing the pdptrace() call is in capability mode, and the security.bsd.allow_ptrace_in_cap_mode tun- able is set to false. [ENOTCAPABLE] The process called pdptrace() on the process descriptor that does not have the CAP_PTRACE capability enabled. SEE ALSO close(2), fork(2), fstat(2), kill(2), kqueue(2), poll(2), wait4(2), cap- sicum(4), procdesc(4) HISTORY The pdfork(), pdgetpid(), and pdkill() system calls first appeared in FreeBSD 9.0. The pdrfork() and pdwait() system calls first appeared in FreeBSD 15.1. The pdopenpid() and pddupfd() system calls first appeared in FreeBSD 16.0. Support for process descriptors mode was developed as part of the TrustedBSD Project. AUTHORS These functions and the capability facility were created by Robert N. M. Watson <rwatson@FreeBSD.org> and Jonathan Anderson <jonathan@FreeBSD.org> at the University of Cambridge Computer Laboratory with support from a grant from Google, Inc. The pdrfork() and pdwait() functions were devel- oped by Konstantin Belousov <kib@FreeBSD.org> with input from Alan Somers <asomers@FreeBSD.org>. The pdopenpid(), pddupfd(), and pdptrace() func- tions were developed by Konstantin Belousov <kib@FreeBSD.org>. FreeBSD 16.0 CURRENT April 19, 2026 PDFORK(2)
NAME | LIBRARY | SYNOPSIS | DESCRIPTION | INTERACTION OF PROCESS DESCRIPTORS WITH OTHER SYSTEM CALLS | RETURN VALUES | ERRORS | SEE ALSO | HISTORY | AUTHORS
Want to link to this manual page? Use this URL:
<https://man.FreeBSD.org/cgi/man.cgi?query=pdwait&sektion=2&manpath=FreeBSD+16.0-CURRENT>