about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-28 09:59:03 +0000
committerbors <bors@rust-lang.org>2023-09-28 09:59:03 +0000
commite2d6aa77ed3fdb2ec6ceb4ee05429457768a4c0f (patch)
treea1cb8609f4a4698b8f409790259306f0f11b4f90 /library/std/src
parent6e09cff6d74f19cab171586c8612f03110c33ebd (diff)
parent9bdf9e754e82cadfacdb081ef2b0a0fe8df9be25 (diff)
downloadrust-e2d6aa77ed3fdb2ec6ceb4ee05429457768a4c0f.tar.gz
rust-e2d6aa77ed3fdb2ec6ceb4ee05429457768a4c0f.zip
Auto merge of #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` ( https://github.com/rust-lang/rust/commit/ab08639e5950f5c8a42a2870c9636181308c3686 ) 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.
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/os/unix/process.rs42
-rw-r--r--library/std/src/os/windows/process.rs39
-rw-r--r--library/std/src/sys/unix/pipe.rs8
-rw-r--r--library/std/src/sys/windows/pipe.rs8
4 files changed, 95 insertions, 2 deletions
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 2b40b672d9f..5d9f7430ca2 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -434,6 +434,20 @@ impl From<crate::process::ChildStdin> for OwnedFd {
     }
 }
 
+/// Create a `ChildStdin` from the provided `OwnedFd`.
+///
+/// The provided file descriptor must point to a pipe
+/// with the `CLOEXEC` flag set.
+#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
+impl From<OwnedFd> for process::ChildStdin {
+    #[inline]
+    fn from(fd: OwnedFd) -> process::ChildStdin {
+        let fd = sys::fd::FileDesc::from_inner(fd);
+        let pipe = sys::pipe::AnonPipe::from_inner(fd);
+        process::ChildStdin::from_inner(pipe)
+    }
+}
+
 #[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for crate::process::ChildStdout {
     #[inline]
@@ -450,6 +464,20 @@ impl From<crate::process::ChildStdout> for OwnedFd {
     }
 }
 
+/// Create a `ChildStdout` from the provided `OwnedFd`.
+///
+/// The provided file descriptor must point to a pipe
+/// with the `CLOEXEC` flag set.
+#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
+impl From<OwnedFd> for process::ChildStdout {
+    #[inline]
+    fn from(fd: OwnedFd) -> process::ChildStdout {
+        let fd = sys::fd::FileDesc::from_inner(fd);
+        let pipe = sys::pipe::AnonPipe::from_inner(fd);
+        process::ChildStdout::from_inner(pipe)
+    }
+}
+
 #[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for crate::process::ChildStderr {
     #[inline]
@@ -466,6 +494,20 @@ impl From<crate::process::ChildStderr> for OwnedFd {
     }
 }
 
+/// Create a `ChildStderr` from the provided `OwnedFd`.
+///
+/// The provided file descriptor must point to a pipe
+/// with the `CLOEXEC` flag set.
+#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
+impl From<OwnedFd> for process::ChildStderr {
+    #[inline]
+    fn from(fd: OwnedFd) -> process::ChildStderr {
+        let fd = sys::fd::FileDesc::from_inner(fd);
+        let pipe = sys::pipe::AnonPipe::from_inner(fd);
+        process::ChildStderr::from_inner(pipe)
+    }
+}
+
 /// Returns the OS-assigned process identifier associated with this process's parent.
 #[must_use]
 #[stable(feature = "unix_ppid", since = "1.27.0")]
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs
index 5d87216ff1b..94173825c4a 100644
--- a/library/std/src/os/windows/process.rs
+++ b/library/std/src/os/windows/process.rs
@@ -106,6 +106,45 @@ impl IntoRawHandle for process::ChildStderr {
     }
 }
 
+/// Create a `ChildStdin` from the provided `OwnedHandle`.
+///
+/// The provided handle must be asynchronous, as reading and
+/// writing from and to it is implemented using asynchronous APIs.
+#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
+impl From<OwnedHandle> for process::ChildStdin {
+    fn from(handle: OwnedHandle) -> process::ChildStdin {
+        let handle = sys::handle::Handle::from_inner(handle);
+        let pipe = sys::pipe::AnonPipe::from_inner(handle);
+        process::ChildStdin::from_inner(pipe)
+    }
+}
+
+/// Create a `ChildStdout` from the provided `OwnedHandle`.
+///
+/// The provided handle must be asynchronous, as reading and
+/// writing from and to it is implemented using asynchronous APIs.
+#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
+impl From<OwnedHandle> for process::ChildStdout {
+    fn from(handle: OwnedHandle) -> process::ChildStdout {
+        let handle = sys::handle::Handle::from_inner(handle);
+        let pipe = sys::pipe::AnonPipe::from_inner(handle);
+        process::ChildStdout::from_inner(pipe)
+    }
+}
+
+/// Create a `ChildStderr` from the provided `OwnedHandle`.
+///
+/// The provided handle must be asynchronous, as reading and
+/// writing from and to it is implemented using asynchronous APIs.
+#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")]
+impl From<OwnedHandle> for process::ChildStderr {
+    fn from(handle: OwnedHandle) -> process::ChildStderr {
+        let handle = sys::handle::Handle::from_inner(handle);
+        let pipe = sys::pipe::AnonPipe::from_inner(handle);
+        process::ChildStderr::from_inner(pipe)
+    }
+}
+
 /// Windows-specific extensions to [`process::ExitStatus`].
 ///
 /// This trait is sealed: it cannot be implemented outside the standard library.
diff --git a/library/std/src/sys/unix/pipe.rs b/library/std/src/sys/unix/pipe.rs
index 1239c65a483..33db24e77e4 100644
--- a/library/std/src/sys/unix/pipe.rs
+++ b/library/std/src/sys/unix/pipe.rs
@@ -3,7 +3,7 @@ use crate::mem;
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
 use crate::sys::fd::FileDesc;
 use crate::sys::{cvt, cvt_r};
-use crate::sys_common::IntoInner;
+use crate::sys_common::{FromInner, IntoInner};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Anonymous pipes
@@ -159,3 +159,9 @@ impl FromRawFd for AnonPipe {
         Self(FromRawFd::from_raw_fd(raw_fd))
     }
 }
+
+impl FromInner<FileDesc> for AnonPipe {
+    fn from_inner(fd: FileDesc) -> Self {
+        Self(fd)
+    }
+}
diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs
index d07147eccc1..7624e746f5c 100644
--- a/library/std/src/sys/windows/pipe.rs
+++ b/library/std/src/sys/windows/pipe.rs
@@ -12,7 +12,7 @@ use crate::sys::c;
 use crate::sys::fs::{File, OpenOptions};
 use crate::sys::handle::Handle;
 use crate::sys::hashmap_random_keys;
-use crate::sys_common::IntoInner;
+use crate::sys_common::{FromInner, IntoInner};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Anonymous pipes
@@ -28,6 +28,12 @@ impl IntoInner<Handle> for AnonPipe {
     }
 }
 
+impl FromInner<Handle> for AnonPipe {
+    fn from_inner(inner: Handle) -> AnonPipe {
+        Self { inner }
+    }
+}
+
 pub struct Pipes {
     pub ours: AnonPipe,
     pub theirs: AnonPipe,