mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 11:48:30 +00:00

This commit fixes an issue where if `eprintln!` is used in a TLS destructor it can accidentally cause the process to abort. TLS destructors are executed after `main` returns on the main thread, and at this point we've also deinitialized global `Lazy` values like those which store the `Stderr` and `Stdout` internals. This means that despite handling TLS not being accessible in `eprintln!`, we will fail due to not being able to call `stderr()`. This means that we'll double-panic quickly because panicking also attempt to write to stderr. The fix here is to reimplement the global stderr handle to avoid the need for destruction. This avoids the need for `Lazy` as well as the hidden panic inside of the `stderr` function. Overall this should improve the robustness of printing errors and/or panics in weird situations, since the `stderr` accessor should be infallible in more situations.
67 lines
1.3 KiB
Rust
67 lines
1.3 KiB
Rust
use crate::cell::UnsafeCell;
|
|
|
|
pub struct Mutex {
|
|
locked: UnsafeCell<bool>,
|
|
}
|
|
|
|
unsafe impl Send for Mutex {}
|
|
unsafe impl Sync for Mutex {} // no threads on wasm
|
|
|
|
impl Mutex {
|
|
pub const fn new() -> Mutex {
|
|
Mutex { locked: UnsafeCell::new(false) }
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn init(&mut self) {}
|
|
|
|
#[inline]
|
|
pub unsafe fn lock(&self) {
|
|
let locked = self.locked.get();
|
|
assert!(!*locked, "cannot recursively acquire mutex");
|
|
*locked = true;
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn unlock(&self) {
|
|
*self.locked.get() = false;
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn try_lock(&self) -> bool {
|
|
let locked = self.locked.get();
|
|
if *locked {
|
|
false
|
|
} else {
|
|
*locked = true;
|
|
true
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn destroy(&self) {}
|
|
}
|
|
|
|
// All empty stubs because wasm has no threads yet, so lock acquisition always
|
|
// succeeds.
|
|
pub struct ReentrantMutex {}
|
|
|
|
impl ReentrantMutex {
|
|
pub const unsafe fn uninitialized() -> ReentrantMutex {
|
|
ReentrantMutex {}
|
|
}
|
|
|
|
pub unsafe fn init(&self) {}
|
|
|
|
pub unsafe fn lock(&self) {}
|
|
|
|
#[inline]
|
|
pub unsafe fn try_lock(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
pub unsafe fn unlock(&self) {}
|
|
|
|
pub unsafe fn destroy(&self) {}
|
|
}
|