1 //! Unix-specific extensions to primitives in the [`std::process`] module.
3 //! [`std::process`]: crate::process
5 #![stable(feature = "rust1", since = "1.0.0")]
9 use crate::os
::unix
::io
::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}
;
11 use crate::sealed
::Sealed
;
13 use crate::sys_common
::{AsInner, AsInnerMut, FromInner, IntoInner}
;
15 /// Unix-specific extensions to the [`process::Command`] builder.
17 /// This trait is sealed: it cannot be implemented outside the standard library.
18 /// This is so that future additional methods are not breaking changes.
19 #[stable(feature = "rust1", since = "1.0.0")]
20 pub trait CommandExt
: Sealed
{
21 /// Sets the child process's user ID. This translates to a
22 /// `setuid` call in the child process. Failure in the `setuid`
23 /// call will cause the spawn to fail.
24 #[stable(feature = "rust1", since = "1.0.0")]
27 #[cfg(not(target_os = "vxworks"))] id: u32,
28 #[cfg(target_os = "vxworks")] id: u16,
29 ) -> &mut process
::Command
;
31 /// Similar to `uid`, but sets the group ID of the child process. This has
32 /// the same semantics as the `uid` field.
33 #[stable(feature = "rust1", since = "1.0.0")]
36 #[cfg(not(target_os = "vxworks"))] id: u32,
37 #[cfg(target_os = "vxworks")] id: u16,
38 ) -> &mut process
::Command
;
40 /// Sets the supplementary group IDs for the calling process. Translates to
41 /// a `setgroups` call in the child process.
42 #[unstable(feature = "setgroups", issue = "90747")]
45 #[cfg(not(target_os = "vxworks"))] groups: &[u32],
46 #[cfg(target_os = "vxworks")] groups: &[u16],
47 ) -> &mut process
::Command
;
49 /// Schedules a closure to be run just before the `exec` function is
52 /// The closure is allowed to return an I/O error whose OS error code will
53 /// be communicated back to the parent and returned as an error from when
54 /// the spawn was requested.
56 /// Multiple closures can be registered and they will be called in order of
57 /// their registration. If a closure returns `Err` then no further closures
58 /// will be called and the spawn operation will immediately return with a
61 /// # Notes and Safety
63 /// This closure will be run in the context of the child process after a
64 /// `fork`. This primarily means that any modifications made to memory on
65 /// behalf of this closure will **not** be visible to the parent process.
66 /// This is often a very constrained environment where normal operations
67 /// like `malloc`, accessing environment variables through [`std::env`]
68 /// or acquiring a mutex are not guaranteed to work (due to
69 /// other threads perhaps still running when the `fork` was run).
71 /// For further details refer to the [POSIX fork() specification]
72 /// and the equivalent documentation for any targeted
73 /// platform, especially the requirements around *async-signal-safety*.
75 /// This also means that all resources such as file descriptors and
76 /// memory-mapped regions got duplicated. It is your responsibility to make
77 /// sure that the closure does not violate library invariants by making
78 /// invalid use of these duplicates.
80 /// Panicking in the closure is safe only if all the format arguments for the
81 /// panic message can be safely formatted; this is because although
82 /// `Command` calls [`std::panic::always_abort`](crate::panic::always_abort)
83 /// before calling the pre_exec hook, panic will still try to format the
86 /// When this closure is run, aspects such as the stdio file descriptors and
87 /// working directory have successfully been changed, so output to these
88 /// locations might not appear where intended.
90 /// [POSIX fork() specification]:
91 /// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html
92 /// [`std::env`]: mod@crate::env
93 #[stable(feature = "process_pre_exec", since = "1.34.0")]
94 unsafe fn pre_exec
<F
>(&mut self, f
: F
) -> &mut process
::Command
96 F
: FnMut() -> io
::Result
<()> + Send
+ Sync
+ '
static;
98 /// Schedules a closure to be run just before the `exec` function is
101 /// This method is stable and usable, but it should be unsafe. To fix
102 /// that, it got deprecated in favor of the unsafe [`pre_exec`].
104 /// [`pre_exec`]: CommandExt::pre_exec
105 #[stable(feature = "process_exec", since = "1.15.0")]
106 #[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")]
107 fn before_exec
<F
>(&mut self, f
: F
) -> &mut process
::Command
109 F
: FnMut() -> io
::Result
<()> + Send
+ Sync
+ '
static,
111 unsafe { self.pre_exec(f) }
114 /// Performs all the required setup by this `Command`, followed by calling
115 /// the `execvp` syscall.
117 /// On success this function will not return, and otherwise it will return
118 /// an error indicating why the exec (or another part of the setup of the
119 /// `Command`) failed.
121 /// `exec` not returning has the same implications as calling
122 /// [`process::exit`] – no destructors on the current stack or any other
123 /// thread’s stack will be run. Therefore, it is recommended to only call
124 /// `exec` at a point where it is fine to not run any destructors. Note,
125 /// that the `execvp` syscall independently guarantees that all memory is
126 /// freed and all file descriptors with the `CLOEXEC` option (set by default
127 /// on all file descriptors opened by the standard library) are closed.
129 /// This function, unlike `spawn`, will **not** `fork` the process to create
130 /// a new child. Like spawn, however, the default behavior for the stdio
131 /// descriptors will be to inherited from the current process.
135 /// The process may be in a "broken state" if this function returns in
136 /// error. For example the working directory, environment variables, signal
137 /// handling settings, various user/group information, or aspects of stdio
138 /// file descriptors may have changed. If a "transactional spawn" is
139 /// required to gracefully handle errors it is recommended to use the
140 /// cross-platform `spawn` instead.
141 #[stable(feature = "process_exec2", since = "1.9.0")]
142 fn exec(&mut self) -> io
::Error
;
144 /// Set executable argument
146 /// Set the first process argument, `argv[0]`, to something other than the
147 /// default executable path.
148 #[stable(feature = "process_set_argv0", since = "1.45.0")]
149 fn arg0
<S
>(&mut self, arg
: S
) -> &mut process
::Command
154 #[stable(feature = "rust1", since = "1.0.0")]
155 impl CommandExt
for process
::Command
{
158 #[cfg(not(target_os = "vxworks"))] id: u32,
159 #[cfg(target_os = "vxworks")] id: u16,
160 ) -> &mut process
::Command
{
161 self.as_inner_mut().uid(id
);
167 #[cfg(not(target_os = "vxworks"))] id: u32,
168 #[cfg(target_os = "vxworks")] id: u16,
169 ) -> &mut process
::Command
{
170 self.as_inner_mut().gid(id
);
176 #[cfg(not(target_os = "vxworks"))] groups: &[u32],
177 #[cfg(target_os = "vxworks")] groups: &[u16],
178 ) -> &mut process
::Command
{
179 self.as_inner_mut().groups(groups
);
183 unsafe fn pre_exec
<F
>(&mut self, f
: F
) -> &mut process
::Command
185 F
: FnMut() -> io
::Result
<()> + Send
+ Sync
+ '
static,
187 self.as_inner_mut().pre_exec(Box
::new(f
));
191 fn exec(&mut self) -> io
::Error
{
192 // NOTE: This may *not* be safe to call after `libc::fork`, because it
193 // may allocate. That may be worth fixing at some point in the future.
194 self.as_inner_mut().exec(sys
::process
::Stdio
::Inherit
)
197 fn arg0
<S
>(&mut self, arg
: S
) -> &mut process
::Command
201 self.as_inner_mut().set_arg_0(arg
.as_ref());
206 /// Unix-specific extensions to [`process::ExitStatus`] and
207 /// [`ExitStatusError`](process::ExitStatusError).
209 /// On Unix, `ExitStatus` **does not necessarily represent an exit status**, as
210 /// passed to the `_exit` system call or returned by
211 /// [`ExitStatus::code()`](crate::process::ExitStatus::code). It represents **any wait status**
212 /// as returned by one of the `wait` family of system
215 /// A Unix wait status (a Rust `ExitStatus`) can represent a Unix exit status, but can also
216 /// represent other kinds of process event.
218 /// This trait is sealed: it cannot be implemented outside the standard library.
219 /// This is so that future additional methods are not breaking changes.
220 #[stable(feature = "rust1", since = "1.0.0")]
221 pub trait ExitStatusExt
: Sealed
{
222 /// Creates a new `ExitStatus` or `ExitStatusError` from the raw underlying integer status
223 /// value from `wait`
225 /// The value should be a **wait status, not an exit status**.
229 /// Panics on an attempt to make an `ExitStatusError` from a wait status of `0`.
231 /// Making an `ExitStatus` always succeeds and never panics.
232 #[stable(feature = "exit_status_from", since = "1.12.0")]
233 fn from_raw(raw
: i32) -> Self;
235 /// If the process was terminated by a signal, returns that signal.
237 /// In other words, if `WIFSIGNALED`, this returns `WTERMSIG`.
238 #[stable(feature = "rust1", since = "1.0.0")]
239 fn signal(&self) -> Option
<i32>;
241 /// If the process was terminated by a signal, says whether it dumped core.
242 #[stable(feature = "unix_process_wait_more", since = "1.58.0")]
243 fn core_dumped(&self) -> bool
;
245 /// If the process was stopped by a signal, returns that signal.
247 /// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`. This is only possible if the status came from
248 /// a `wait` system call which was passed `WUNTRACED`, and was then converted into an `ExitStatus`.
249 #[stable(feature = "unix_process_wait_more", since = "1.58.0")]
250 fn stopped_signal(&self) -> Option
<i32>;
252 /// Whether the process was continued from a stopped status.
254 /// Ie, `WIFCONTINUED`. This is only possible if the status came from a `wait` system call
255 /// which was passed `WCONTINUED`, and was then converted into an `ExitStatus`.
256 #[stable(feature = "unix_process_wait_more", since = "1.58.0")]
257 fn continued(&self) -> bool
;
259 /// Returns the underlying raw `wait` status.
261 /// The returned integer is a **wait status, not an exit status**.
262 #[stable(feature = "unix_process_wait_more", since = "1.58.0")]
263 fn into_raw(self) -> i32;
266 #[stable(feature = "rust1", since = "1.0.0")]
267 impl ExitStatusExt
for process
::ExitStatus
{
268 fn from_raw(raw
: i32) -> Self {
269 process
::ExitStatus
::from_inner(From
::from(raw
))
272 fn signal(&self) -> Option
<i32> {
273 self.as_inner().signal()
276 fn core_dumped(&self) -> bool
{
277 self.as_inner().core_dumped()
280 fn stopped_signal(&self) -> Option
<i32> {
281 self.as_inner().stopped_signal()
284 fn continued(&self) -> bool
{
285 self.as_inner().continued()
288 fn into_raw(self) -> i32 {
289 self.as_inner().into_raw().into()
293 #[unstable(feature = "exit_status_error", issue = "84908")]
294 impl ExitStatusExt
for process
::ExitStatusError
{
295 fn from_raw(raw
: i32) -> Self {
296 process
::ExitStatus
::from_raw(raw
)
298 .expect_err("<ExitStatusError as ExitStatusExt>::from_raw(0) but zero is not an error")
301 fn signal(&self) -> Option
<i32> {
302 self.into_status().signal()
305 fn core_dumped(&self) -> bool
{
306 self.into_status().core_dumped()
309 fn stopped_signal(&self) -> Option
<i32> {
310 self.into_status().stopped_signal()
313 fn continued(&self) -> bool
{
314 self.into_status().continued()
317 fn into_raw(self) -> i32 {
318 self.into_status().into_raw()
322 #[stable(feature = "process_extensions", since = "1.2.0")]
323 impl FromRawFd
for process
::Stdio
{
325 unsafe fn from_raw_fd(fd
: RawFd
) -> process
::Stdio
{
326 let fd
= sys
::fd
::FileDesc
::from_raw_fd(fd
);
327 let io
= sys
::process
::Stdio
::Fd(fd
);
328 process
::Stdio
::from_inner(io
)
332 #[unstable(feature = "io_safety", issue = "87074")]
333 impl From
<OwnedFd
> for process
::Stdio
{
335 fn from(fd
: OwnedFd
) -> process
::Stdio
{
336 let fd
= sys
::fd
::FileDesc
::from_inner(fd
);
337 let io
= sys
::process
::Stdio
::Fd(fd
);
338 process
::Stdio
::from_inner(io
)
342 #[stable(feature = "process_extensions", since = "1.2.0")]
343 impl AsRawFd
for process
::ChildStdin
{
345 fn as_raw_fd(&self) -> RawFd
{
346 self.as_inner().as_raw_fd()
350 #[stable(feature = "process_extensions", since = "1.2.0")]
351 impl AsRawFd
for process
::ChildStdout
{
353 fn as_raw_fd(&self) -> RawFd
{
354 self.as_inner().as_raw_fd()
358 #[stable(feature = "process_extensions", since = "1.2.0")]
359 impl AsRawFd
for process
::ChildStderr
{
361 fn as_raw_fd(&self) -> RawFd
{
362 self.as_inner().as_raw_fd()
366 #[stable(feature = "into_raw_os", since = "1.4.0")]
367 impl IntoRawFd
for process
::ChildStdin
{
369 fn into_raw_fd(self) -> RawFd
{
370 self.into_inner().into_inner().into_raw_fd()
374 #[stable(feature = "into_raw_os", since = "1.4.0")]
375 impl IntoRawFd
for process
::ChildStdout
{
377 fn into_raw_fd(self) -> RawFd
{
378 self.into_inner().into_inner().into_raw_fd()
382 #[stable(feature = "into_raw_os", since = "1.4.0")]
383 impl IntoRawFd
for process
::ChildStderr
{
385 fn into_raw_fd(self) -> RawFd
{
386 self.into_inner().into_inner().into_raw_fd()
390 #[unstable(feature = "io_safety", issue = "87074")]
391 impl AsFd
for crate::process
::ChildStdin
{
393 fn as_fd(&self) -> BorrowedFd
<'_
> {
394 self.as_inner().as_fd()
398 #[unstable(feature = "io_safety", issue = "87074")]
399 impl From
<crate::process
::ChildStdin
> for OwnedFd
{
401 fn from(child_stdin
: crate::process
::ChildStdin
) -> OwnedFd
{
402 child_stdin
.into_inner().into_inner().into_inner()
406 #[unstable(feature = "io_safety", issue = "87074")]
407 impl AsFd
for crate::process
::ChildStdout
{
409 fn as_fd(&self) -> BorrowedFd
<'_
> {
410 self.as_inner().as_fd()
414 #[unstable(feature = "io_safety", issue = "87074")]
415 impl From
<crate::process
::ChildStdout
> for OwnedFd
{
417 fn from(child_stdout
: crate::process
::ChildStdout
) -> OwnedFd
{
418 child_stdout
.into_inner().into_inner().into_inner()
422 #[unstable(feature = "io_safety", issue = "87074")]
423 impl AsFd
for crate::process
::ChildStderr
{
425 fn as_fd(&self) -> BorrowedFd
<'_
> {
426 self.as_inner().as_fd()
430 #[unstable(feature = "io_safety", issue = "87074")]
431 impl From
<crate::process
::ChildStderr
> for OwnedFd
{
433 fn from(child_stderr
: crate::process
::ChildStderr
) -> OwnedFd
{
434 child_stderr
.into_inner().into_inner().into_inner()
438 /// Returns the OS-assigned process identifier associated with this process's parent.
440 #[stable(feature = "unix_ppid", since = "1.27.0")]
441 pub fn parent_id() -> u32 {
442 crate::sys
::os
::getppid()