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