migrate compiler, bootstrap, and compiletest to windows-rs
This commit is contained in:
@@ -27,52 +27,54 @@
|
||||
//! Note that this module has a #[cfg(windows)] above it as none of this logic
|
||||
//! is required on Unix.
|
||||
|
||||
#![allow(nonstandard_style, dead_code)]
|
||||
|
||||
use crate::Build;
|
||||
use std::env;
|
||||
use std::ffi::c_void;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use winapi::shared::minwindef::{DWORD, FALSE, LPVOID};
|
||||
use winapi::um::errhandlingapi::SetErrorMode;
|
||||
use winapi::um::handleapi::{CloseHandle, DuplicateHandle};
|
||||
use winapi::um::jobapi2::{AssignProcessToJobObject, CreateJobObjectW, SetInformationJobObject};
|
||||
use winapi::um::processthreadsapi::{GetCurrentProcess, OpenProcess};
|
||||
use winapi::um::winbase::{BELOW_NORMAL_PRIORITY_CLASS, SEM_NOGPFAULTERRORBOX};
|
||||
use winapi::um::winnt::{
|
||||
JobObjectExtendedLimitInformation, DUPLICATE_SAME_ACCESS, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS, PROCESS_DUP_HANDLE,
|
||||
use windows::{
|
||||
core::PCWSTR,
|
||||
Win32::Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE},
|
||||
Win32::System::Diagnostics::Debug::{SetErrorMode, SEM_NOGPFAULTERRORBOX, THREAD_ERROR_MODE},
|
||||
Win32::System::JobObjects::{
|
||||
AssignProcessToJobObject, CreateJobObjectW, JobObjectExtendedLimitInformation,
|
||||
SetInformationJobObject, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS,
|
||||
},
|
||||
Win32::System::Threading::{
|
||||
GetCurrentProcess, OpenProcess, BELOW_NORMAL_PRIORITY_CLASS, PROCESS_DUP_HANDLE,
|
||||
},
|
||||
};
|
||||
|
||||
pub unsafe fn setup(build: &mut Build) {
|
||||
// Enable the Windows Error Reporting dialog which msys disables,
|
||||
// so we can JIT debug rustc
|
||||
let mode = SetErrorMode(0);
|
||||
let mode = SetErrorMode(THREAD_ERROR_MODE::default());
|
||||
let mode = THREAD_ERROR_MODE(mode);
|
||||
SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX);
|
||||
|
||||
// Create a new job object for us to use
|
||||
let job = CreateJobObjectW(ptr::null_mut(), ptr::null());
|
||||
assert!(!job.is_null(), "{}", io::Error::last_os_error());
|
||||
let job = CreateJobObjectW(None, PCWSTR::null()).unwrap();
|
||||
|
||||
// Indicate that when all handles to the job object are gone that all
|
||||
// process in the object should be killed. Note that this includes our
|
||||
// entire process tree by default because we've added ourselves and our
|
||||
// children will reside in the job by default.
|
||||
let mut info = mem::zeroed::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>();
|
||||
let mut info = JOBOBJECT_EXTENDED_LIMIT_INFORMATION::default();
|
||||
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||
if build.config.low_priority {
|
||||
info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
|
||||
info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
|
||||
info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS.0;
|
||||
}
|
||||
let r = SetInformationJobObject(
|
||||
job,
|
||||
JobObjectExtendedLimitInformation,
|
||||
&mut info as *mut _ as LPVOID,
|
||||
mem::size_of_val(&info) as DWORD,
|
||||
);
|
||||
assert!(r != 0, "{}", io::Error::last_os_error());
|
||||
&info as *const _ as *const c_void,
|
||||
mem::size_of_val(&info) as u32,
|
||||
)
|
||||
.ok();
|
||||
assert!(r.is_ok(), "{}", io::Error::last_os_error());
|
||||
|
||||
// Assign our process to this job object. Note that if this fails, one very
|
||||
// likely reason is that we are ourselves already in a job object! This can
|
||||
@@ -83,8 +85,8 @@ pub unsafe fn setup(build: &mut Build) {
|
||||
// Also note that nested jobs (why this might fail) are supported in recent
|
||||
// versions of Windows, but the version of Windows that our bots are running
|
||||
// at least don't support nested job objects.
|
||||
let r = AssignProcessToJobObject(job, GetCurrentProcess());
|
||||
if r == 0 {
|
||||
let r = AssignProcessToJobObject(job, GetCurrentProcess()).ok();
|
||||
if r.is_err() {
|
||||
CloseHandle(job);
|
||||
return;
|
||||
}
|
||||
@@ -102,31 +104,32 @@ pub unsafe fn setup(build: &mut Build) {
|
||||
Err(..) => return,
|
||||
};
|
||||
|
||||
let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap());
|
||||
let parent = match OpenProcess(PROCESS_DUP_HANDLE, false, pid.parse().unwrap()).ok() {
|
||||
Some(parent) => parent,
|
||||
_ => {
|
||||
// If we get a null parent pointer here, it is possible that either
|
||||
// we have an invalid pid or the parent process has been closed.
|
||||
// Since the first case rarely happens
|
||||
// (only when wrongly setting the environmental variable),
|
||||
// it might be better to improve the experience of the second case
|
||||
// when users have interrupted the parent process and we haven't finish
|
||||
// duplicating the handle yet. We just need close the job object if that occurs.
|
||||
CloseHandle(job);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// If we get a null parent pointer here, it is possible that either
|
||||
// we have got an invalid pid or the parent process has been closed.
|
||||
// Since the first case rarely happens
|
||||
// (only when wrongly setting the environmental variable),
|
||||
// so it might be better to improve the experience of the second case
|
||||
// when users have interrupted the parent process and we don't finish
|
||||
// duplicating the handle yet.
|
||||
// We just need close the job object if that occurs.
|
||||
if parent.is_null() {
|
||||
CloseHandle(job);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut parent_handle = ptr::null_mut();
|
||||
let mut parent_handle = HANDLE::default();
|
||||
let r = DuplicateHandle(
|
||||
GetCurrentProcess(),
|
||||
job,
|
||||
parent,
|
||||
&mut parent_handle,
|
||||
0,
|
||||
FALSE,
|
||||
false,
|
||||
DUPLICATE_SAME_ACCESS,
|
||||
);
|
||||
)
|
||||
.ok();
|
||||
|
||||
// If this failed, well at least we tried! An example of DuplicateHandle
|
||||
// failing in the past has been when the wrong python2 package spawned this
|
||||
@@ -134,7 +137,7 @@ pub unsafe fn setup(build: &mut Build) {
|
||||
// `mingw-w64-x86_64-python2`. Not sure why it failed, but the "failure
|
||||
// mode" here is that we only clean everything up when the build system
|
||||
// dies, not when the python parent does, so not too bad.
|
||||
if r != 0 {
|
||||
if r.is_err() {
|
||||
CloseHandle(job);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user