|
6 | 6 |
|
7 | 7 | use crate::io::Result; |
8 | 8 | use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; |
9 | | -use crate::process; |
| 9 | +use crate::process::{self, ExitStatus}; |
10 | 10 | use crate::sealed::Sealed; |
11 | | -#[cfg(not(doc))] |
12 | 11 | use crate::sys::fd::FileDesc; |
| 12 | +#[cfg(not(doc))] |
| 13 | +use crate::sys::linux::pidfd::PidFd as InnerPidFd; |
13 | 14 | use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; |
14 | 15 |
|
15 | 16 | #[cfg(doc)] |
16 | | -struct FileDesc; |
| 17 | +struct InnerPidFd; |
17 | 18 |
|
18 | 19 | /// This type represents a file descriptor that refers to a process. |
19 | 20 | /// |
@@ -47,63 +48,98 @@ struct FileDesc; |
47 | 48 | /// [`take_pidfd`]: ChildExt::take_pidfd |
48 | 49 | /// [`pidfd_open(2)`]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html |
49 | 50 | #[derive(Debug)] |
| 51 | +#[repr(transparent)] |
50 | 52 | pub struct PidFd { |
51 | | - inner: FileDesc, |
| 53 | + inner: InnerPidFd, |
| 54 | +} |
| 55 | + |
| 56 | +impl PidFd { |
| 57 | + /// Forces the child process to exit. |
| 58 | + /// |
| 59 | + /// Unlike [`Child::kill`] it is possible to attempt to kill |
| 60 | + /// reaped children since PidFd does not suffer from pid recycling |
| 61 | + /// races. But doing so will return an Error. |
| 62 | + /// |
| 63 | + /// [`Child::kill`]: process::Child::kill |
| 64 | + pub fn kill(&self) -> Result<()> { |
| 65 | + self.inner.kill() |
| 66 | + } |
| 67 | + |
| 68 | + /// Waits for the child to exit completely, returning the status that it exited with. |
| 69 | + /// |
| 70 | + /// Unlike [`Child::wait`] it does not ensure that the stdin handle is closed. |
| 71 | + /// Additionally it will not return an `ExitStatus` if the child |
| 72 | + /// has alrady been reaped. Instead an error will be returned. |
| 73 | + /// |
| 74 | + /// [`Child::wait`]: process::Child::wait |
| 75 | + pub fn wait(&self) -> Result<ExitStatus> { |
| 76 | + self.inner.wait().map(FromInner::from_inner) |
| 77 | + } |
| 78 | + |
| 79 | + /// Attempts to collect the exit status of the child if it has already exited. |
| 80 | + /// |
| 81 | + /// Unlike [`Child::try_wait`] this method will return an Error |
| 82 | + /// if the child has already been reaped. |
| 83 | + /// |
| 84 | + /// [`Child::try_wait`]: process::Child::try_wait |
| 85 | + pub fn try_wait(&self) -> Result<Option<ExitStatus>> { |
| 86 | + Ok(self.inner.try_wait()?.map(FromInner::from_inner)) |
| 87 | + } |
52 | 88 | } |
53 | 89 |
|
54 | | -impl AsInner<FileDesc> for PidFd { |
| 90 | +impl AsInner<InnerPidFd> for PidFd { |
55 | 91 | #[inline] |
56 | | - fn as_inner(&self) -> &FileDesc { |
| 92 | + fn as_inner(&self) -> &InnerPidFd { |
57 | 93 | &self.inner |
58 | 94 | } |
59 | 95 | } |
60 | 96 |
|
61 | | -impl FromInner<FileDesc> for PidFd { |
62 | | - fn from_inner(inner: FileDesc) -> PidFd { |
| 97 | +impl FromInner<InnerPidFd> for PidFd { |
| 98 | + fn from_inner(inner: InnerPidFd) -> PidFd { |
63 | 99 | PidFd { inner } |
64 | 100 | } |
65 | 101 | } |
66 | 102 |
|
67 | | -impl IntoInner<FileDesc> for PidFd { |
68 | | - fn into_inner(self) -> FileDesc { |
| 103 | +impl IntoInner<InnerPidFd> for PidFd { |
| 104 | + fn into_inner(self) -> InnerPidFd { |
69 | 105 | self.inner |
70 | 106 | } |
71 | 107 | } |
72 | 108 |
|
73 | 109 | impl AsRawFd for PidFd { |
74 | 110 | #[inline] |
75 | 111 | fn as_raw_fd(&self) -> RawFd { |
76 | | - self.as_inner().as_raw_fd() |
| 112 | + self.as_inner().as_inner().as_raw_fd() |
77 | 113 | } |
78 | 114 | } |
79 | 115 |
|
80 | 116 | impl FromRawFd for PidFd { |
81 | 117 | unsafe fn from_raw_fd(fd: RawFd) -> Self { |
82 | | - Self::from_inner(FileDesc::from_raw_fd(fd)) |
| 118 | + Self::from_inner(InnerPidFd::from_raw_fd(fd)) |
83 | 119 | } |
84 | 120 | } |
85 | 121 |
|
86 | 122 | impl IntoRawFd for PidFd { |
87 | 123 | fn into_raw_fd(self) -> RawFd { |
88 | | - self.into_inner().into_raw_fd() |
| 124 | + self.into_inner().into_inner().into_raw_fd() |
89 | 125 | } |
90 | 126 | } |
91 | 127 |
|
92 | 128 | impl AsFd for PidFd { |
93 | 129 | fn as_fd(&self) -> BorrowedFd<'_> { |
94 | | - self.as_inner().as_fd() |
| 130 | + self.as_inner().as_inner().as_fd() |
95 | 131 | } |
96 | 132 | } |
97 | 133 |
|
98 | 134 | impl From<OwnedFd> for PidFd { |
99 | 135 | fn from(fd: OwnedFd) -> Self { |
100 | | - Self::from_inner(FileDesc::from_inner(fd)) |
| 136 | + Self::from_inner(InnerPidFd::from_inner(FileDesc::from_inner(fd))) |
101 | 137 | } |
102 | 138 | } |
103 | 139 |
|
104 | 140 | impl From<PidFd> for OwnedFd { |
105 | 141 | fn from(pid_fd: PidFd) -> Self { |
106 | | - pid_fd.into_inner().into_inner() |
| 142 | + pid_fd.into_inner().into_inner().into_inner() |
107 | 143 | } |
108 | 144 | } |
109 | 145 |
|
|
0 commit comments