Skip to content

Commit 540709b

Browse files
seritoolsmbilker
authored andcommitted
Add fallback implementation for GetProcessId
Since that API is only available starting from XP SP1/Server 2003, we'll have to get a bit creative to emulate the same behavior on older systems: We'll have to query whether the process has exited by `WaitForSingleObject` with a timeout of 0 (= non-blocking). If `WAIT_TIMEOUT` is returned, the process has not exited, so our saved process id is still valid (MSDN: "The value is valid from the time the process is created until the time the process is terminated."). If the process has exited, the wait will succeed and return `WAIT_OBJECT_0`, in which case the id is no longer valid, and we return 0, just like `GetProcessId`.
1 parent 697f800 commit 540709b

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

library/std/src/sys/windows/c.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,12 @@ compat_fn_with_fallback! {
401401
pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE) -> () {
402402
rtabort!("unavailable")
403403
}
404+
405+
// >= XP SP1 / Vista / Server 2003
406+
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocessid
407+
pub fn GetProcessId(handle: HANDLE) -> DWORD {
408+
rtabort!("unavailable")
409+
}
404410
}
405411

406412
compat_fn_optional! {

library/std/src/sys/windows/c/windows_sys.lst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2517,7 +2517,6 @@ Windows.Win32.System.Threading.GetCurrentProcess
25172517
Windows.Win32.System.Threading.GetCurrentProcessId
25182518
Windows.Win32.System.Threading.GetCurrentThread
25192519
Windows.Win32.System.Threading.GetExitCodeProcess
2520-
Windows.Win32.System.Threading.GetProcessId
25212520
Windows.Win32.System.Threading.HIGH_PRIORITY_CLASS
25222521
Windows.Win32.System.Threading.IDLE_PRIORITY_CLASS
25232522
Windows.Win32.System.Threading.INFINITE

library/std/src/sys/windows/c/windows_sys.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,6 @@ extern "system" {
318318
pub fn GetProcAddress(hmodule: HMODULE, lpprocname: PCSTR) -> FARPROC;
319319
}
320320
#[link(name = "kernel32")]
321-
extern "system" {
322-
pub fn GetProcessId(process: HANDLE) -> u32;
323-
}
324-
#[link(name = "kernel32")]
325321
extern "system" {
326322
pub fn GetStdHandle(nstdhandle: STD_HANDLE) -> HANDLE;
327323
}

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ impl Command {
342342
Process {
343343
handle: Handle::from_raw_handle(pi.hProcess),
344344
main_thread_handle: Handle::from_raw_handle(pi.hThread),
345+
id: pi.dwProcessId,
345346
},
346347
pipes,
347348
))
@@ -591,6 +592,7 @@ impl From<File> for Stdio {
591592
pub struct Process {
592593
handle: Handle,
593594
main_thread_handle: Handle,
595+
id: u32,
594596
}
595597

596598
impl Process {
@@ -600,7 +602,25 @@ impl Process {
600602
}
601603

602604
pub fn id(&self) -> u32 {
603-
unsafe { c::GetProcessId(self.handle.as_raw_handle()) as u32 }
605+
if c::GetProcessId::available() {
606+
unsafe { c::GetProcessId(self.handle.as_raw_handle()) as u32 }
607+
} else {
608+
// Query whether the process has exited by waiting with a timeout of 0 (= non-blocking).
609+
// If `WAIT_TIMEOUT` is returned, the process has not exited, so our saved process id is
610+
// still valid (MSDN: "The value is valid from the time the process is created until the
611+
// time the process is terminated."). If the process has exited, the wait will succeed
612+
// and return `WAIT_OBJECT_0`, in which case the id is no longer valid, and we return 0,
613+
// just like `GetProcessId`.
614+
let res = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), 0) };
615+
616+
match res {
617+
c::WAIT_TIMEOUT => self.id,
618+
c::WAIT_OBJECT_0 | _ => {
619+
// process is exited, there is no valid id associated anymore
620+
0
621+
}
622+
}
623+
}
604624
}
605625

606626
pub fn main_thread_handle(&self) -> BorrowedHandle<'_> {

0 commit comments

Comments
 (0)