|
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