std/sys/pal/unix/linux/
pidfd.rs

1use crate::io;
2use crate::os::fd::{AsRawFd, FromRawFd, RawFd};
3use crate::sys::fd::FileDesc;
4use crate::sys::process::ExitStatus;
5use crate::sys::{AsInner, FromInner, IntoInner, cvt};
6
7#[cfg(test)]
8mod tests;
9
10#[derive(Debug)]
11pub(crate) struct PidFd(FileDesc);
12
13impl PidFd {
14    pub fn kill(&self) -> io::Result<()> {
15        self.send_signal(libc::SIGKILL)
16    }
17
18    pub(crate) fn send_signal(&self, signal: i32) -> io::Result<()> {
19        cvt(unsafe {
20            libc::syscall(
21                libc::SYS_pidfd_send_signal,
22                self.0.as_raw_fd(),
23                signal,
24                crate::ptr::null::<()>(),
25                0,
26            )
27        })
28        .map(drop)
29    }
30
31    pub fn wait(&self) -> io::Result<ExitStatus> {
32        let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() };
33        cvt(unsafe {
34            libc::waitid(libc::P_PIDFD, self.0.as_raw_fd() as u32, &mut siginfo, libc::WEXITED)
35        })?;
36        Ok(ExitStatus::from_waitid_siginfo(siginfo))
37    }
38
39    pub fn try_wait(&self) -> io::Result<Option<ExitStatus>> {
40        let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() };
41
42        cvt(unsafe {
43            libc::waitid(
44                libc::P_PIDFD,
45                self.0.as_raw_fd() as u32,
46                &mut siginfo,
47                libc::WEXITED | libc::WNOHANG,
48            )
49        })?;
50        if unsafe { siginfo.si_pid() } == 0 {
51            Ok(None)
52        } else {
53            Ok(Some(ExitStatus::from_waitid_siginfo(siginfo)))
54        }
55    }
56}
57
58impl AsInner<FileDesc> for PidFd {
59    fn as_inner(&self) -> &FileDesc {
60        &self.0
61    }
62}
63
64impl IntoInner<FileDesc> for PidFd {
65    fn into_inner(self) -> FileDesc {
66        self.0
67    }
68}
69
70impl FromInner<FileDesc> for PidFd {
71    fn from_inner(inner: FileDesc) -> Self {
72        Self(inner)
73    }
74}
75
76impl FromRawFd for PidFd {
77    unsafe fn from_raw_fd(fd: RawFd) -> Self {
78        Self(FileDesc::from_raw_fd(fd))
79    }
80}