rustc_errors/
lock.rs

1//! Bindings to acquire a global named lock.
2//!
3//! This is intended to be used to synchronize multiple compiler processes to
4//! ensure that we can output complete errors without interleaving on Windows.
5//! Note that this is currently only needed for allowing only one 32-bit MSVC
6//! linker to execute at once on MSVC hosts, so this is only implemented for
7//! `cfg(windows)`. Also note that this may not always be used on Windows,
8//! only when targeting 32-bit MSVC.
9//!
10//! For more information about why this is necessary, see where this is called.
11
12use std::any::Any;
13
14#[cfg(windows)]
15pub(crate) fn acquire_global_lock(name: &str) -> Box<dyn Any> {
16    use std::ffi::CString;
17    use std::io;
18
19    use windows::Win32::Foundation::{CloseHandle, HANDLE, WAIT_ABANDONED, WAIT_OBJECT_0};
20    use windows::Win32::System::Threading::{
21        CreateMutexA, INFINITE, ReleaseMutex, WaitForSingleObject,
22    };
23    use windows::core::PCSTR;
24
25    struct Handle(HANDLE);
26
27    impl Drop for Handle {
28        fn drop(&mut self) {
29            unsafe {
30                // FIXME can panic here
31                CloseHandle(self.0).unwrap();
32            }
33        }
34    }
35
36    struct Guard(Handle);
37
38    impl Drop for Guard {
39        fn drop(&mut self) {
40            unsafe {
41                // FIXME can panic here
42                ReleaseMutex((self.0).0).unwrap();
43            }
44        }
45    }
46
47    let cname = CString::new(name).unwrap();
48    // Create a named mutex, with no security attributes and also not
49    // acquired when we create it.
50    //
51    // This will silently create one if it doesn't already exist, or it'll
52    // open up a handle to one if it already exists.
53    let mutex = unsafe { CreateMutexA(None, false, PCSTR::from_raw(cname.as_ptr().cast())) }
54        .unwrap_or_else(|_| panic!("failed to create global mutex named `{}`", name));
55    let mutex = Handle(mutex);
56
57    // Acquire the lock through `WaitForSingleObject`.
58    //
59    // A return value of `WAIT_OBJECT_0` means we successfully acquired it.
60    //
61    // A return value of `WAIT_ABANDONED` means that the previous holder of
62    // the thread exited without calling `ReleaseMutex`. This can happen,
63    // for example, when the compiler crashes or is interrupted via ctrl-c
64    // or the like. In this case, however, we are still transferred
65    // ownership of the lock so we continue.
66    //
67    // If an error happens.. well... that's surprising!
68    match unsafe { WaitForSingleObject(mutex.0, INFINITE) } {
69        WAIT_OBJECT_0 | WAIT_ABANDONED => (),
70        err => panic!(
71            "WaitForSingleObject failed on global mutex named `{}`: {} (ret={:x})",
72            name,
73            io::Error::last_os_error(),
74            err.0
75        ),
76    }
77
78    // Return a guard which will call `ReleaseMutex` when dropped.
79    Box::new(Guard(mutex))
80}
81
82#[cfg(not(windows))]
83pub(crate) fn acquire_global_lock(_name: &str) -> Box<dyn Any> {
84    Box::new(())
85}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy