Skip to content

Commit 68cb170

Browse files
committed
std: prevent CreateProcess() race on Windows
Believe or not, `CreateProcess()` is racy if several threads create child processes: [0], [1], [2]. This caused some tests show crash dialogs during `make check-stage#-rpass`. More explanation: On Windows, `SetErrorMode()` controls display of error dialogs: it accepts new error mode and returns old error mode. The error mode is process-global and automatically inherited to child process when created. MSYS2 bash shell internally sets it to not show error dialogs, therefore `make check-stage#-rpass` should not show them either. However, [1] says that `CreateProcess()` internally invokes `SetErrorMode()` twice: at first it sets mode `0x8001` and saves original mode, and at second it restores original mode. So if two threads simultaneously call `CreateProcess()`, the first thread sets error mode to `0x8001` then the second thread recognizes that current error mode is `0x8001`. Therefore, The second thread will create process with wrong error mode. This really occurs inside `compiletest`: it creates several processes on each thread, so some `run-pass` tests are invoked with wrong error mode therefore show crash dialog. This commit adds `StaticMutex` for `CreateProcess()` call. This seems to fix the "dialog annoyance" issue. [0]: http://support.microsoft.com/kb/315939 [1]: https://code.google.com/p/nativeclient/issues/detail?id=2968 [2]: https://ghc.haskell.org/trac/ghc/ticket/2650
1 parent 8efd990 commit 68cb170

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

src/libstd/sys/windows/process.rs

+7
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,19 @@ use path::BytesContainer;
2525
use ptr;
2626
use str;
2727
use sys::fs::FileDesc;
28+
use sync::{StaticMutex, MUTEX_INIT};
29+
2830
use sys::fs;
2931
use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
3032
use sys_common::helper_thread::Helper;
3133
use sys_common::{AsInner, mkerr_libc, timeout};
3234

3335
pub use sys_common::ProcessConfig;
3436

37+
// `CreateProcess` is racy!
38+
// http://support.microsoft.com/kb/315939
39+
static CREATE_PROCESS_LOCK: StaticMutex = MUTEX_INIT;
40+
3541
/// A value representing a child process.
3642
///
3743
/// The lifetime of this value is linked to the lifetime of the actual
@@ -224,6 +230,7 @@ impl Process {
224230
with_dirp(cfg.cwd(), |dirp| {
225231
let mut cmd_str: Vec<u16> = cmd_str.utf16_units().collect();
226232
cmd_str.push(0);
233+
let _lock = CREATE_PROCESS_LOCK.lock().unwrap();
227234
let created = CreateProcessW(ptr::null(),
228235
cmd_str.as_mut_ptr(),
229236
ptr::null_mut(),

0 commit comments

Comments
 (0)