1 use std::io; 2 use std::os::windows::io::{AsRawHandle, RawHandle}; 3 use std::process::Child; 4 use windows_sys::Win32::Foundation::{HANDLE, WAIT_OBJECT_0, WAIT_TIMEOUT}; 5 use windows_sys::Win32::System::Threading::{WaitForSingleObject, INFINITE}; 6 7 pub struct Handle(RawHandle); 8 9 // Kind of like a child PID on Unix, it's important not to keep the handle 10 // around after the child has been cleaned up. The best solution would be to 11 // have the handle actually borrow the child, but we need to keep the child 12 // unborrowed. Instead we just avoid storing them. get_handle(child: &Child) -> Handle13pub fn get_handle(child: &Child) -> Handle { 14 Handle(child.as_raw_handle()) 15 } 16 17 // This is very similar to libstd's Child::wait implementation, because the 18 // basic wait on Windows doesn't reap. The main difference is that this can be 19 // called without &mut Child. wait_without_reaping(handle: Handle) -> io::Result<()>20pub fn wait_without_reaping(handle: Handle) -> io::Result<()> { 21 let wait_ret = unsafe { WaitForSingleObject(handle.0 as HANDLE, INFINITE) }; 22 if wait_ret != WAIT_OBJECT_0 { 23 Err(io::Error::last_os_error()) 24 } else { 25 Ok(()) 26 } 27 } 28 try_wait_without_reaping(handle: Handle) -> io::Result<bool>29pub fn try_wait_without_reaping(handle: Handle) -> io::Result<bool> { 30 let wait_ret = unsafe { WaitForSingleObject(handle.0 as HANDLE, 0) }; 31 if wait_ret == WAIT_OBJECT_0 { 32 // Child has exited. 33 Ok(true) 34 } else if wait_ret == WAIT_TIMEOUT { 35 // Child has not exited yet. 36 Ok(false) 37 } else { 38 Err(io::Error::last_os_error()) 39 } 40 } 41