|
| 1 | +//! Interfaces for Linux's PID file descriptors. |
| 2 | +
|
| 3 | +use std::os::unix::io::RawFd; |
| 4 | +use crate::Result; |
| 5 | +use crate::errno::Errno; |
| 6 | +use crate::unistd::Pid; |
| 7 | + |
| 8 | +libc_bitflags!( |
| 9 | + /// Options that change the behavior of [`pidfd_open`]. |
| 10 | + pub struct PidFdOpenFlag: libc::c_uint { |
| 11 | + /// Return a nonblocking file descriptor. (since Linux 5.10) |
| 12 | + /// |
| 13 | + /// If the process referred to by the file descriptor has not yet terminated, |
| 14 | + /// then an attempt to wait on the file descriptor using [`waitid(2)`] will |
| 15 | + /// immediately return the error `EAGAIN` rather than blocking. |
| 16 | + /// |
| 17 | + /// [`waitid(2)`]: https://man7.org/linux/man-pages/man2/waitid.2.html |
| 18 | + PIDFD_NONBLOCK; |
| 19 | + } |
| 20 | +); |
| 21 | + |
| 22 | +/// Obtain a file descriptor that refers to a process. (since Linux 5.3) |
| 23 | +/// |
| 24 | +/// The `pidfd_open(2)` creates a file descriptor that refers to the process |
| 25 | +/// whose PID is specified in pid. The file descriptor is returned as the function |
| 26 | +/// result; the close-on-exec flag is set on the file descriptor. |
| 27 | +/// |
| 28 | +/// For more information, see [`pidfd_open(2)`]. |
| 29 | +/// |
| 30 | +/// [`pidfd_open(2)`]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html |
| 31 | +pub fn pidfd_open(pid: Pid, flags: PidFdOpenFlag) -> Result<RawFd> { |
| 32 | + let ret = unsafe { |
| 33 | + libc::syscall(libc::SYS_pidfd_open, pid, flags) |
| 34 | + }; |
| 35 | + Errno::result(ret).map(|r| r as RawFd) |
| 36 | +} |
| 37 | + |
| 38 | +/// Obtain a duplicate of another process's file descriptor. (since Linux 5.6) |
| 39 | +/// |
| 40 | +/// The `pidfd_getfd(2)` system call allocates a new file descriptor in the calling |
| 41 | +/// process. This new file descriptor is a duplicate of an existing file descriptor, |
| 42 | +/// `target_fd`, in the process referred to by the PID file descriptor pidfd. |
| 43 | +/// |
| 44 | +/// For more information, see [`pidfd_getfd(2)`]. |
| 45 | +/// |
| 46 | +/// [`pidfd_getfd(2)`]: https://man7.org/linux/man-pages/man2/pidfd_getfd.2.html |
| 47 | +pub fn pidfd_getfd(pidfd: RawFd, target_fd: RawFd) -> Result<RawFd> { |
| 48 | + let ret = unsafe { |
| 49 | + libc::syscall(libc::SYS_pidfd_getfd, pidfd, target_fd, 0) |
| 50 | + }; |
| 51 | + Errno::result(ret).map(|r| r as RawFd) |
| 52 | +} |
| 53 | + |
| 54 | +/// Send a signal to a process specified by a file descriptor. |
| 55 | +/// |
| 56 | +/// The `pidfd_send_signal(2)` system call sends the signal sig to the target process |
| 57 | +/// referred to by pidfd, a PID file descriptor that refers to a process. |
| 58 | +/// |
| 59 | +/// For more information, see [`pidfd_send_signal(2)`]. |
| 60 | +/// |
| 61 | +/// [`pidfd_send_signal(2)`]: https://man7.org/linux/man-pages/man2/pidfd_send_signal.2.html |
| 62 | +#[cfg(feature = "signal")] |
| 63 | +pub fn pidfd_send_signal<T: Into<Option<crate::sys::signal::Signal>>>(pidfd: RawFd, signal: T, sig_info: Option<&libc::siginfo_t>) -> Result<()> { |
| 64 | + let signal = match signal.into() { |
| 65 | + Some(signal) => signal as libc::c_int, |
| 66 | + _ => 0, |
| 67 | + }; |
| 68 | + let ret = unsafe { |
| 69 | + libc::syscall(libc::SYS_pidfd_send_signal, pidfd, signal, sig_info, 0) |
| 70 | + }; |
| 71 | + Errno::result(ret).map(drop) |
| 72 | +} |
0 commit comments