Skip to content

Commit 4134d3e

Browse files
Abstract ProcThreadAttributeList into its own struct
1 parent 279c9ba commit 4134d3e

File tree

3 files changed

+217
-133
lines changed

3 files changed

+217
-133
lines changed

library/std/src/os/windows/process.rs

+27-39
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
#![stable(feature = "process_extensions", since = "1.2.0")]
66

77
use crate::ffi::OsStr;
8+
use crate::io;
89
use crate::os::windows::io::{
910
AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
1011
};
1112
use crate::process;
1213
use crate::sealed::Sealed;
1314
use crate::sys;
1415
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
16+
#[unstable(feature = "windows_process_extensions_raw_attribute", issue = "114854")]
17+
pub use sys::process::{ProcThreadAttributeList, ProcThreadAttributeListBuilder};
1518

1619
#[stable(feature = "process_extensions", since = "1.2.0")]
1720
impl FromRawHandle for process::Stdio {
@@ -235,29 +238,21 @@ pub trait CommandExt: Sealed {
235238
#[unstable(feature = "windows_process_extensions_async_pipes", issue = "98289")]
236239
fn async_pipes(&mut self, always_async: bool) -> &mut process::Command;
237240

238-
/// Sets a raw attribute on the command, providing extended configuration options for Windows processes.
241+
/// Executes the command as a child process with the given [`ProcThreadAttributeList`], returning a handle to it.
239242
///
240-
/// This method allows you to specify custom attributes for a child process on Windows systems using raw attribute values.
241-
/// Raw attributes provide extended configurability for process creation, but their usage can be complex and potentially unsafe.
242-
///
243-
/// The `attribute` parameter specifies the raw attribute to be set, while the `value` parameter holds the value associated with that attribute.
244-
/// Please refer to the [`windows-rs`](https://microsoft.github.io/windows-docs-rs/doc/windows/) documentation or the [`Win32 API documentation`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute) for detailed information about available attributes and their meanings.
243+
/// This method enables the customization of attributes for the spawned child process on Windows systems.
244+
/// Attributes offer extended configurability for process creation, but their usage can be intricate and potentially unsafe.
245245
///
246246
/// # Note
247247
///
248-
/// The maximum number of raw attributes is the value of [`u32::MAX`].
249-
/// If this limit is exceeded, the call to [`process::Command::spawn`] will return an `Error` indicating that the maximum number of attributes has been exceeded.
250-
/// # Safety
251-
///
252-
/// The usage of raw attributes is potentially unsafe and should be done with caution. Incorrect attribute values or improper configuration can lead to unexpected behavior or errors.
248+
/// By default, stdin, stdout, and stderr are inherited from the parent process.
253249
///
254250
/// # Example
255251
///
256-
/// The following example demonstrates how to create a child process with a specific parent process ID using a raw attribute.
257-
///
258-
/// ```rust
252+
/// ```
259253
/// #![feature(windows_process_extensions_raw_attribute)]
260-
/// use std::os::windows::{process::CommandExt, io::AsRawHandle};
254+
/// use std::os::windows::process::CommandExt;
255+
/// use std::os::windows::io::AsRawHandle;
261256
/// use std::process::Command;
262257
///
263258
/// # struct ProcessDropGuard(std::process::Child);
@@ -266,34 +261,27 @@ pub trait CommandExt: Sealed {
266261
/// # let _ = self.0.kill();
267262
/// # }
268263
/// # }
269-
///
264+
/// #
270265
/// let parent = Command::new("cmd").spawn()?;
271-
///
272-
/// let mut child_cmd = Command::new("cmd");
266+
/// let parent_process_handle = parent.as_raw_handle();
267+
/// # let parent = ProcessDropGuard(parent);
273268
///
274269
/// const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000;
270+
/// let mut attribute_list = ProcThreadAttributeList::build()
271+
/// .attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parent_process_handle)
272+
/// .finish()
273+
/// .unwrap();
275274
///
276-
/// unsafe {
277-
/// child_cmd.raw_attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parent.as_raw_handle() as isize);
278-
/// }
275+
/// let mut child = child_cmd.spawn_with_attributes(attribute_list)?;
279276
/// #
280-
/// # let parent = ProcessDropGuard(parent);
281-
///
282-
/// let mut child = child_cmd.spawn()?;
283-
///
284277
/// # child.kill()?;
285278
/// # Ok::<(), std::io::Error>(())
286279
/// ```
287-
///
288-
/// # Safety Note
289-
///
290-
/// Remember that improper use of raw attributes can lead to undefined behavior or security vulnerabilities. Always consult the documentation and ensure proper attribute values are used.
291280
#[unstable(feature = "windows_process_extensions_raw_attribute", issue = "114854")]
292-
unsafe fn raw_attribute<T: Copy + Send + Sync + 'static>(
281+
fn spawn_with_attributes(
293282
&mut self,
294-
attribute: usize,
295-
value: T,
296-
) -> &mut process::Command;
283+
attribute_list: &mut ProcThreadAttributeList<'_>,
284+
) -> io::Result<process::Child>;
297285
}
298286

299287
#[stable(feature = "windows_process_extensions", since = "1.16.0")]
@@ -322,13 +310,13 @@ impl CommandExt for process::Command {
322310
self
323311
}
324312

325-
unsafe fn raw_attribute<T: Copy + Send + Sync + 'static>(
313+
fn spawn_with_attributes(
326314
&mut self,
327-
attribute: usize,
328-
value: T,
329-
) -> &mut process::Command {
330-
self.as_inner_mut().raw_attribute(attribute, value);
331-
self
315+
attribute_list: &mut ProcThreadAttributeList<'_>,
316+
) -> io::Result<process::Child> {
317+
self.as_inner_mut()
318+
.spawn_with_attributes(sys::process::Stdio::Inherit, true, Some(attribute_list))
319+
.map(process::Child::from_inner)
332320
}
333321
}
334322

library/std/src/process/tests.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ fn test_proc_thread_attributes() {
442442
use crate::mem;
443443
use crate::os::windows::io::AsRawHandle;
444444
use crate::os::windows::process::CommandExt;
445+
use crate::os::windows::process::ProcThreadAttributeList;
445446
use crate::sys::c::{CloseHandle, BOOL, HANDLE};
446447
use crate::sys::cvt;
447448

@@ -481,12 +482,14 @@ fn test_proc_thread_attributes() {
481482

482483
let mut child_cmd = Command::new("cmd");
483484

484-
unsafe {
485-
child_cmd
486-
.raw_attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parent.0.as_raw_handle() as isize);
487-
}
485+
let parent_process_handle = parent.0.as_raw_handle();
486+
487+
let mut attribute_list = ProcThreadAttributeList::build()
488+
.attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parent_process_handle)
489+
.finish()
490+
.unwrap();
488491

489-
let child = ProcessDropGuard(child_cmd.spawn().unwrap());
492+
let child = ProcessDropGuard(child_cmd.spawn_with_attributes(&mut attribute_list).unwrap());
490493

491494
let h_snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
492495

0 commit comments

Comments
 (0)