std/sys/pal/unix/linux/
pidfd.rs1use 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}