diff options
| author | Michael van Straten <michael@vanstraten.de> | 2023-08-25 16:19:16 +0200 | 
|---|---|---|
| committer | Michael van Straten <michael@vanstraten.de> | 2023-08-25 16:30:34 +0200 | 
| commit | edefa8b105cd4a35b689e85187689f4fb4085ede (patch) | |
| tree | cdfe88612e167bf4bd4e8cd225e73f4c8a5171b0 /library/std/src/process/tests.rs | |
| parent | d7e751006cb3691d1384b74196a9cb45447acfa8 (diff) | |
| download | rust-edefa8b105cd4a35b689e85187689f4fb4085ede.tar.gz rust-edefa8b105cd4a35b689e85187689f4fb4085ede.zip | |
Added option to set ProcThreadAttributes for Windows processes
This implements the ability to add arbitrary attributes to a command on Windows targets using a new `raw_attribute` method on the [`CommandExt`](https://doc.rust-lang.org/stable/std/os/windows/process/trait.CommandExt.html) trait. Setting these attributes provides extended configuration options for Windows processes. Co-authored-by: Tyler Ruckinger <t.ruckinger@gmail.com>
Diffstat (limited to 'library/std/src/process/tests.rs')
| -rw-r--r-- | library/std/src/process/tests.rs | 85 | 
1 files changed, 85 insertions, 0 deletions
| diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 366b591466c..00636237288 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -434,6 +434,91 @@ fn test_creation_flags() { assert!(events > 0); } +/// Tests proc thread attributes by spawning a process with a custom parent process, +/// then comparing the parent process ID with the expected parent process ID. +#[test] +#[cfg(windows)] +fn test_proc_thread_attributes() { + use crate::mem; + use crate::os::windows::io::AsRawHandle; + use crate::os::windows::process::CommandExt; + use crate::sys::c::{CloseHandle, BOOL, HANDLE}; + use crate::sys::cvt; + + #[repr(C)] + #[allow(non_snake_case)] + struct PROCESSENTRY32W { + dwSize: u32, + cntUsage: u32, + th32ProcessID: u32, + th32DefaultHeapID: usize, + th32ModuleID: u32, + cntThreads: u32, + th32ParentProcessID: u32, + pcPriClassBase: i32, + dwFlags: u32, + szExeFile: [u16; 260], + } + + extern "system" { + fn CreateToolhelp32Snapshot(dwflags: u32, th32processid: u32) -> HANDLE; + fn Process32First(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL; + fn Process32Next(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL; + } + + const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000; + const TH32CS_SNAPPROCESS: u32 = 0x00000002; + + struct ProcessDropGuard(crate::process::Child); + + impl Drop for ProcessDropGuard { + fn drop(&mut self) { + let _ = self.0.kill(); + } + } + + let parent = ProcessDropGuard(Command::new("cmd").spawn().unwrap()); + + let mut child_cmd = Command::new("cmd"); + + unsafe { + child_cmd + .raw_attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parent.0.as_raw_handle() as isize); + } + + let child = ProcessDropGuard(child_cmd.spawn().unwrap()); + + let h_snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) }; + + let mut process_entry = PROCESSENTRY32W { + dwSize: mem::size_of::<PROCESSENTRY32W>() as u32, + cntUsage: 0, + th32ProcessID: 0, + th32DefaultHeapID: 0, + th32ModuleID: 0, + cntThreads: 0, + th32ParentProcessID: 0, + pcPriClassBase: 0, + dwFlags: 0, + szExeFile: [0; 260], + }; + + unsafe { cvt(Process32First(h_snapshot, &mut process_entry as *mut _)) }.unwrap(); + + loop { + if child.0.id() == process_entry.th32ProcessID { + break; + } + unsafe { cvt(Process32Next(h_snapshot, &mut process_entry as *mut _)) }.unwrap(); + } + + unsafe { cvt(CloseHandle(h_snapshot)) }.unwrap(); + + assert_eq!(parent.0.id(), process_entry.th32ParentProcessID); + + drop(child) +} + #[test] fn test_command_implements_send_sync() { fn take_send_sync_type<T: Send + Sync>(_: T) {} | 
