about summary refs log tree commit diff
path: root/src/libstd/process.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-12-05 06:53:56 +0000
committerbors <bors@rust-lang.org>2016-12-05 06:53:56 +0000
commitb4f4b65f9934b2728e9be0c02855aba3b31ad311 (patch)
treeb016cf9e2fc2c3bd023d3d014e1966589a83ddad /src/libstd/process.rs
parent6bc551a261de4b62a50761e624dc8fd27c85c4ce (diff)
parente6975e974841c59a6e67e8a158b306f29d35d513 (diff)
downloadrust-b4f4b65f9934b2728e9be0c02855aba3b31ad311.tar.gz
rust-b4f4b65f9934b2728e9be0c02855aba3b31ad311.zip
Auto merge of #38098 - luser:windows-commandext, r=alexcrichton
Add std::os::windows::process::CommandExt. Fixes #37827

This adds a CommandExt trait for Windows along with an implementation of it
for std::process::Command with methods to set the process creation flags that
are passed to CreateProcess.
Diffstat (limited to 'src/libstd/process.rs')
-rw-r--r--src/libstd/process.rs58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 9e1b57c7412..bfc36d5b21f 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1167,4 +1167,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);
+    }
 }