Auto merge of #124101 - the8472:pidfd-methods, r=cuviper · model-checking/verify-rust-std@934e728 (original) (raw)
`@@ -6,20 +6,20 @@
`
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
`///
`
20
20
`` /// A PidFd
can be obtained by setting the corresponding option on [Command
]
``
21
21
`` /// with [create_pidfd
]. Subsequently, the created pidfd can be retrieved
``
22
``
`` -
/// from the [Child
] by calling [pidfd
] or [take_pidfd
].
``
``
22
`` +
/// from the [Child
] by calling [pidfd
] or [into_pidfd
].
``
23
23
`///
`
24
24
`/// Example:
`
25
25
```` /// ```no_run
````
`@@ -33,7 +33,7 @@ struct FileDesc;
`
33
33
`/// .expect("Failed to spawn child");
`
34
34
`///
`
35
35
`/// let pidfd = child
`
36
``
`-
/// .take_pidfd()
`
``
36
`+
/// .into_pidfd()
`
37
37
`/// .expect("Failed to retrieve pidfd");
`
38
38
`///
`
39
39
`` /// // The file descriptor will be closed when pidfd
is dropped.
``
`@@ -44,66 +44,101 @@ struct FileDesc;
`
44
44
`` /// [create_pidfd
]: CommandExt::create_pidfd
``
45
45
`` /// [Child
]: process::Child
``
46
46
`` /// [pidfd
]: fn@ChildExt::pidfd
``
47
``
`` -
/// [take_pidfd
]: ChildExt::take_pidfd
``
``
47
`` +
/// [into_pidfd
]: ChildExt::into_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 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 {
`
``
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> {
`
``
85
`+
Ok(self.inner.try_wait()?.map(FromInner::from_inner))
`
``
86
`+
}
`
``
87
`+
}
`
``
88
+
``
89
`+
impl AsInner 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 for PidFd {
`
62
``
`-
fn from_inner(inner: FileDesc) -> PidFd {
`
``
96
`+
impl FromInner for PidFd {
`
``
97
`+
fn from_inner(inner: InnerPidFd) -> PidFd {
`
63
98
`PidFd { inner }
`
64
99
`}
`
65
100
`}
`
66
101
``
67
``
`-
impl IntoInner for PidFd {
`
68
``
`-
fn into_inner(self) -> FileDesc {
`
``
102
`+
impl IntoInner 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 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 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
``
`@@ -124,18 +159,26 @@ pub trait ChildExt: Sealed {
`
124
159
`` /// [Child
]: process::Child
``
125
160
`fn pidfd(&self) -> Result<&PidFd>;
`
126
161
``
127
``
`` -
/// Takes ownership of the [PidFd
] created for this [Child
], if available.
``
``
162
`` +
/// Returns the [PidFd
] created for this [Child
], if available.
``
``
163
`+
/// Otherwise self is returned.
`
128
164
`///
`
129
165
`/// A pidfd will only be available if its creation was requested with
`
130
166
`` /// [create_pidfd
] when the corresponding [Command
] was created.
``
131
167
`///
`
``
168
`+
/// Taking ownership of the PidFd consumes the Child to avoid pid reuse
`
``
169
`` +
/// races. Use [pidfd
] and [BorrowedFd::try_clone_to_owned
] if
``
``
170
`+
/// you don't want to disassemble the Child yet.
`
``
171
`+
///
`
132
172
`/// Even if requested, a pidfd may not be available due to an older
`
133
173
`/// version of Linux being in use, or if some other error occurred.
`
134
174
`///
`
135
175
`` /// [Command
]: process::Command
``
136
176
`` /// [create_pidfd
]: CommandExt::create_pidfd
``
``
177
`` +
/// [pidfd
]: ChildExt::pidfd
``
137
178
`` /// [Child
]: process::Child
``
138
``
`-
fn take_pidfd(&mut self) -> Result;
`
``
179
`+
fn into_pidfd(self) -> crate::result::Result<PidFd, Self>
`
``
180
`+
where
`
``
181
`+
Self: Sized;
`
139
182
`}
`
140
183
``
141
184
`` /// Os-specific extensions for [Command
]
``
`@@ -146,7 +189,7 @@ pub trait CommandExt: Sealed {
`
146
189
`` /// spawned by this [Command
].
``
147
190
`/// By default, no pidfd will be created.
`
148
191
`///
`
149
``
`` -
/// The pidfd can be retrieved from the child with [pidfd
] or [take_pidfd
].
``
``
192
`` +
/// The pidfd can be retrieved from the child with [pidfd
] or [into_pidfd
].
``
150
193
`///
`
151
194
`/// A pidfd will only be created if it is possible to do so
`
152
195
`` /// in a guaranteed race-free manner. Otherwise, [pidfd
] will return an error.
``
`@@ -160,7 +203,7 @@ pub trait CommandExt: Sealed {
`
160
203
`` /// [Command
]: process::Command
``
161
204
`` /// [Child
]: process::Child
``
162
205
`` /// [pidfd
]: fn@ChildExt::pidfd
``
163
``
`` -
/// [take_pidfd
]: ChildExt::take_pidfd
``
``
206
`` +
/// [into_pidfd
]: ChildExt::into_pidfd
``
164
207
`fn create_pidfd(&mut self, val: bool) -> &mut process::Command;
`
165
208
`}
`
166
209
``