diff --git a/src/libpanic_unwind/windows.rs b/src/libpanic_unwind/windows.rs index fd8429d262e6e..a7e90071ceae8 100644 --- a/src/libpanic_unwind/windows.rs +++ b/src/libpanic_unwind/windows.rs @@ -12,11 +12,11 @@ #![allow(dead_code)] #![cfg(windows)] -use libc::{c_long, c_ulong, c_ulonglong, c_void}; +use libc::{c_long, c_ulong, c_void}; pub type DWORD = c_ulong; pub type LONG = c_long; -pub type ULONG_PTR = c_ulonglong; +pub type ULONG_PTR = usize; pub type LPVOID = *mut c_void; pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; diff --git a/src/librustc_data_structures/flock.rs b/src/librustc_data_structures/flock.rs index 32f0fd4199776..ff1ebb11b7221 100644 --- a/src/librustc_data_structures/flock.rs +++ b/src/librustc_data_structures/flock.rs @@ -247,11 +247,11 @@ mod imp { use std::os::windows::raw::HANDLE; use std::path::Path; use std::fs::{File, OpenOptions}; - use std::os::raw::{c_ulong, c_ulonglong, c_int}; + use std::os::raw::{c_ulong, c_int}; type DWORD = c_ulong; type BOOL = c_int; - type ULONG_PTR = c_ulonglong; + type ULONG_PTR = usize; type LPOVERLAPPED = *mut OVERLAPPED; const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x00000002; diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 4daab31c28f49..965776a241d00 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -14,8 +14,9 @@ #![cfg_attr(test, allow(dead_code))] #![unstable(issue = "0", feature = "windows_c")] -use os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort,}; -use os::raw::{c_char, c_ulonglong}; +use os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort, c_char}; +#[cfg(target_arch = "x86_64")] +use os::raw::c_ulonglong; use libc::{wchar_t, size_t, c_void}; use ptr; @@ -45,7 +46,7 @@ pub type SIZE_T = usize; pub type WORD = u16; pub type CHAR = c_char; pub type HCRYPTPROV = LONG_PTR; -pub type ULONG_PTR = c_ulonglong; +pub type ULONG_PTR = usize; pub type ULONG = c_ulong; #[cfg(target_arch = "x86_64")] pub type ULONGLONG = u64; @@ -282,9 +283,12 @@ pub const CRYPT_SILENT: DWORD = 64; pub const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000; pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0; +pub const EXCEPTION_CONTINUE_EXECUTION: LONG = -1; pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd; pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; +pub const MS_VC_EXCEPTION: DWORD = 0x406d1388; + pub const PIPE_ACCESS_INBOUND: DWORD = 0x00000001; pub const PIPE_ACCESS_OUTBOUND: DWORD = 0x00000002; pub const FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD = 0x00080000; @@ -833,6 +837,15 @@ pub struct CONSOLE_READCONSOLE_CONTROL { } pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct THREADNAME_INFO { + pub dwType: DWORD, + pub szName: LPCSTR, + pub dwThreadID: DWORD, + pub dwFlags: DWORD, +} + extern "system" { pub fn WSAStartup(wVersionRequested: WORD, lpWSAData: LPWSADATA) -> c_int; @@ -1122,6 +1135,11 @@ extern "system" { lpOverlapped: LPOVERLAPPED, lpNumberOfBytesTransferred: LPDWORD, bWait: BOOL) -> BOOL; + + pub fn RaiseException(dwExceptionCode: DWORD, + dwExceptionFlags: DWORD, + nNumberOfArguments: DWORD, + lpArguments: *const ULONG_PTR); } // Functions that aren't available on Windows XP, but we still use them and just diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 5a376a867ee64..33d18724a050f 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -18,6 +18,22 @@ use sys::c; use sys::handle::Handle; use sys_common::thread::*; use time::Duration; +use cell::Cell; +use sync; + +thread_local! { + static IGNORE_EXCEPTIONS: Cell = Cell::new(false); +} + +extern "system" +fn exception_filter(_ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> c::LONG { + IGNORE_EXCEPTIONS.with(|ignoring| { + match ignoring.get() { + true => c::EXCEPTION_CONTINUE_EXECUTION, + false => c::EXCEPTION_CONTINUE_SEARCH, + } + }) +} pub struct Thread { handle: Handle @@ -53,11 +69,40 @@ impl Thread { } } - pub fn set_name(_name: &CStr) { - // Windows threads are nameless - // The names in MSVC debugger are obtained using a "magic" exception, - // which requires a use of MS C++ extensions. - // See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx + pub fn set_name(name: &CStr) { + // Most Windows debuggers support setting thread names by throwing a + // magic exception. Windows itself is unaware of the exceptions + // non-exceptional meaning and will crash the process if nothing + // catches it, so we register an exception handler to filter them. + // See: https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx + + static FILTER_INIT: sync::Once = sync::ONCE_INIT; + + FILTER_INIT.call_once(|| { + unsafe { + if c::AddVectoredExceptionHandler(0, exception_filter).is_null() { + panic!("failed to install exception filter"); + } + } + }); + + let info = c::THREADNAME_INFO { + dwType: 0x1000, + szName: name.as_ptr(), + dwThreadID: 0xffffffff, + dwFlags: 0, + }; + + let size = (mem::size_of::() / + mem::size_of::()) as c::DWORD; + + let args = &info as *const _ as *const _; + + IGNORE_EXCEPTIONS.with(|ignoring| { + ignoring.set(true); + unsafe { c::RaiseException(c::MS_VC_EXCEPTION, 0, size, args); } + ignoring.set(false); + }); } pub fn join(self) {