Skip to content

Commit e2d6aa7

Browse files
committed
Auto merge of rust-lang#98704 - vthib:impl-from-raw-for-childstd-structs, r=dtolnay
Implement From<OwnedFd/Handle> for ChildStdin/out/err object ## Summary Comments in `library/std/src/process.rs` ( rust-lang@ab08639 ) indicates that `ChildStdin`, `ChildStdout`, `ChildStderr` implements some traits that are not actually implemented: `FromRawFd`, `FromRawHandle`, and the `From<OwnedFd>/From<OwnedHandle>` from the io_safety feature. In this PR I implement `FromRawHandle` and `FromRawFd` for those 3 objects. ## Usecase I have a usecase where those implementations are basically needed. I want to customize in the `Command::spawn` API how the pipes for the parent/child communications are created (mainly to strengthen the security attributes on them). I can properly setup the pipes, and the "child" handles can be provided to `Child::spawn` easily using `Stdio::from_raw_handle`. However, there is no way to generate the `ChildStd*` objects from the raw handle of the created name pipe, which would be very useful to still expose the same API than in other OS (basically a `spawn(...) -> (Child, ChildStdin, ChildStdout, ChildSterr)`, where on windows this is customized), and to for example use `tokio::ChildStdin::from_std` afterwards. ## Questions * Are those impls OK to add? I have searched to see if those impls were missing on purpose, or if it was just never implemented because never needed. I haven't found any indication on why they couldn't be added, although the user clearly has to be very careful that the handle provided makes sense (i think, mainly that it is in overlapped mode for windows). * If this change is ok, adding the impls for the io_safety feature would probably be best, or should it be done in another PR? * I just copy-pasted the `#[stable(...)]` attributes, but the `since` value has to be updated, I'm not sure to which value.
2 parents 6e09cff + 9bdf9e7 commit e2d6aa7

File tree

4 files changed

+95
-2
lines changed

4 files changed

+95
-2
lines changed

Diff for: library/std/src/os/unix/process.rs

+42
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,20 @@ impl From<crate::process::ChildStdin> for OwnedFd {
434434
}
435435
}
436436

437+
/// Create a `ChildStdin` from the provided `OwnedFd`.
438+
///
439+
/// The provided file descriptor must point to a pipe
440+
/// with the `CLOEXEC` flag set.
441+
#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
442+
impl From<OwnedFd> for process::ChildStdin {
443+
#[inline]
444+
fn from(fd: OwnedFd) -> process::ChildStdin {
445+
let fd = sys::fd::FileDesc::from_inner(fd);
446+
let pipe = sys::pipe::AnonPipe::from_inner(fd);
447+
process::ChildStdin::from_inner(pipe)
448+
}
449+
}
450+
437451
#[stable(feature = "io_safety", since = "1.63.0")]
438452
impl AsFd for crate::process::ChildStdout {
439453
#[inline]
@@ -450,6 +464,20 @@ impl From<crate::process::ChildStdout> for OwnedFd {
450464
}
451465
}
452466

467+
/// Create a `ChildStdout` from the provided `OwnedFd`.
468+
///
469+
/// The provided file descriptor must point to a pipe
470+
/// with the `CLOEXEC` flag set.
471+
#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
472+
impl From<OwnedFd> for process::ChildStdout {
473+
#[inline]
474+
fn from(fd: OwnedFd) -> process::ChildStdout {
475+
let fd = sys::fd::FileDesc::from_inner(fd);
476+
let pipe = sys::pipe::AnonPipe::from_inner(fd);
477+
process::ChildStdout::from_inner(pipe)
478+
}
479+
}
480+
453481
#[stable(feature = "io_safety", since = "1.63.0")]
454482
impl AsFd for crate::process::ChildStderr {
455483
#[inline]
@@ -466,6 +494,20 @@ impl From<crate::process::ChildStderr> for OwnedFd {
466494
}
467495
}
468496

497+
/// Create a `ChildStderr` from the provided `OwnedFd`.
498+
///
499+
/// The provided file descriptor must point to a pipe
500+
/// with the `CLOEXEC` flag set.
501+
#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
502+
impl From<OwnedFd> for process::ChildStderr {
503+
#[inline]
504+
fn from(fd: OwnedFd) -> process::ChildStderr {
505+
let fd = sys::fd::FileDesc::from_inner(fd);
506+
let pipe = sys::pipe::AnonPipe::from_inner(fd);
507+
process::ChildStderr::from_inner(pipe)
508+
}
509+
}
510+
469511
/// Returns the OS-assigned process identifier associated with this process's parent.
470512
#[must_use]
471513
#[stable(feature = "unix_ppid", since = "1.27.0")]

Diff for: library/std/src/os/windows/process.rs

+39
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,45 @@ impl IntoRawHandle for process::ChildStderr {
106106
}
107107
}
108108

109+
/// Create a `ChildStdin` from the provided `OwnedHandle`.
110+
///
111+
/// The provided handle must be asynchronous, as reading and
112+
/// writing from and to it is implemented using asynchronous APIs.
113+
#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
114+
impl From<OwnedHandle> for process::ChildStdin {
115+
fn from(handle: OwnedHandle) -> process::ChildStdin {
116+
let handle = sys::handle::Handle::from_inner(handle);
117+
let pipe = sys::pipe::AnonPipe::from_inner(handle);
118+
process::ChildStdin::from_inner(pipe)
119+
}
120+
}
121+
122+
/// Create a `ChildStdout` from the provided `OwnedHandle`.
123+
///
124+
/// The provided handle must be asynchronous, as reading and
125+
/// writing from and to it is implemented using asynchronous APIs.
126+
#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
127+
impl From<OwnedHandle> for process::ChildStdout {
128+
fn from(handle: OwnedHandle) -> process::ChildStdout {
129+
let handle = sys::handle::Handle::from_inner(handle);
130+
let pipe = sys::pipe::AnonPipe::from_inner(handle);
131+
process::ChildStdout::from_inner(pipe)
132+
}
133+
}
134+
135+
/// Create a `ChildStderr` from the provided `OwnedHandle`.
136+
///
137+
/// The provided handle must be asynchronous, as reading and
138+
/// writing from and to it is implemented using asynchronous APIs.
139+
#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
140+
impl From<OwnedHandle> for process::ChildStderr {
141+
fn from(handle: OwnedHandle) -> process::ChildStderr {
142+
let handle = sys::handle::Handle::from_inner(handle);
143+
let pipe = sys::pipe::AnonPipe::from_inner(handle);
144+
process::ChildStderr::from_inner(pipe)
145+
}
146+
}
147+
109148
/// Windows-specific extensions to [`process::ExitStatus`].
110149
///
111150
/// This trait is sealed: it cannot be implemented outside the standard library.

Diff for: library/std/src/sys/unix/pipe.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::mem;
33
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
44
use crate::sys::fd::FileDesc;
55
use crate::sys::{cvt, cvt_r};
6-
use crate::sys_common::IntoInner;
6+
use crate::sys_common::{FromInner, IntoInner};
77

88
////////////////////////////////////////////////////////////////////////////////
99
// Anonymous pipes
@@ -159,3 +159,9 @@ impl FromRawFd for AnonPipe {
159159
Self(FromRawFd::from_raw_fd(raw_fd))
160160
}
161161
}
162+
163+
impl FromInner<FileDesc> for AnonPipe {
164+
fn from_inner(fd: FileDesc) -> Self {
165+
Self(fd)
166+
}
167+
}

Diff for: library/std/src/sys/windows/pipe.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::sys::c;
1212
use crate::sys::fs::{File, OpenOptions};
1313
use crate::sys::handle::Handle;
1414
use crate::sys::hashmap_random_keys;
15-
use crate::sys_common::IntoInner;
15+
use crate::sys_common::{FromInner, IntoInner};
1616

1717
////////////////////////////////////////////////////////////////////////////////
1818
// Anonymous pipes
@@ -28,6 +28,12 @@ impl IntoInner<Handle> for AnonPipe {
2828
}
2929
}
3030

31+
impl FromInner<Handle> for AnonPipe {
32+
fn from_inner(inner: Handle) -> AnonPipe {
33+
Self { inner }
34+
}
35+
}
36+
3137
pub struct Pipes {
3238
pub ours: AnonPipe,
3339
pub theirs: AnonPipe,

0 commit comments

Comments
 (0)