diff options
| author | Jeremy Soller <jackpot51@gmail.com> | 2016-12-12 14:55:09 -0700 |
|---|---|---|
| committer | Jeremy Soller <jackpot51@gmail.com> | 2016-12-12 14:55:09 -0700 |
| commit | 7e7775ce7bfc916ce723bd1fdaf4ae54662c6627 (patch) | |
| tree | 235a9c38e42bacdb671da33bc49ffc8a4aba17a4 /src/libstd/process.rs | |
| parent | c61baa0fc7a85bd2bcce34aac05ed739261cf037 (diff) | |
| parent | 6483bdd860fd89fc68846d4cc94c7ae3307a84c1 (diff) | |
| download | rust-7e7775ce7bfc916ce723bd1fdaf4ae54662c6627.tar.gz rust-7e7775ce7bfc916ce723bd1fdaf4ae54662c6627.zip | |
Merge branch 'master' into redox
Diffstat (limited to 'src/libstd/process.rs')
| -rw-r--r-- | src/libstd/process.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/libstd/process.rs b/src/libstd/process.rs index c99fda9febc..858537dd2de 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -253,6 +253,14 @@ impl Command { /// Builder methods are provided to change these defaults and /// otherwise configure the process. /// + /// If `program` is not an absolute path, the `PATH` will be searched in + /// an OS-defined way. + /// + /// The search path to be used may be controlled by setting the + /// `PATH` environment variable on the Command, + /// but this has some implementation limitations on Windows + /// (see https://github.com/rust-lang/rust/issues/37519). + /// /// # Examples /// /// Basic usage: @@ -819,6 +827,14 @@ impl Child { /// will be run. If a clean shutdown is needed it is recommended to only call /// this function at a known point where there are no more destructors left /// to run. +/// +/// # Examples +/// +/// ``` +/// use std::process; +/// +/// process::exit(0); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn exit(code: i32) -> ! { ::sys_common::cleanup(); @@ -1159,4 +1175,62 @@ mod tests { Ok(_) => panic!(), } } + + /// Test that process creation flags work by debugging a process. + /// Other creation flags make it hard or impossible to detect + /// behavioral changes in the process. + #[test] + #[cfg(windows)] + fn test_creation_flags() { + use os::windows::process::CommandExt; + use sys::c::{BOOL, DWORD, INFINITE}; + #[repr(C, packed)] + struct DEBUG_EVENT { + pub event_code: DWORD, + pub process_id: DWORD, + pub thread_id: DWORD, + // This is a union in the real struct, but we don't + // need this data for the purposes of this test. + pub _junk: [u8; 164], + } + + extern "system" { + fn WaitForDebugEvent(lpDebugEvent: *mut DEBUG_EVENT, dwMilliseconds: DWORD) -> BOOL; + fn ContinueDebugEvent(dwProcessId: DWORD, dwThreadId: DWORD, + dwContinueStatus: DWORD) -> BOOL; + } + + const DEBUG_PROCESS: DWORD = 1; + const EXIT_PROCESS_DEBUG_EVENT: DWORD = 5; + const DBG_EXCEPTION_NOT_HANDLED: DWORD = 0x80010001; + + let mut child = Command::new("cmd") + .creation_flags(DEBUG_PROCESS) + .stdin(Stdio::piped()).spawn().unwrap(); + child.stdin.take().unwrap().write_all(b"exit\r\n").unwrap(); + let mut events = 0; + let mut event = DEBUG_EVENT { + event_code: 0, + process_id: 0, + thread_id: 0, + _junk: [0; 164], + }; + loop { + if unsafe { WaitForDebugEvent(&mut event as *mut DEBUG_EVENT, INFINITE) } == 0 { + panic!("WaitForDebugEvent failed!"); + } + events += 1; + + if event.event_code == EXIT_PROCESS_DEBUG_EVENT { + break; + } + + if unsafe { ContinueDebugEvent(event.process_id, + event.thread_id, + DBG_EXCEPTION_NOT_HANDLED) } == 0 { + panic!("ContinueDebugEvent failed!"); + } + } + assert!(events > 0); + } } |
