Skip to content

Commit 361cd7b

Browse files
committed
std: do not wrap platform locks in sys_common; remove StaticMutex and StaticRwLock
1 parent 75b7e52 commit 361cd7b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+745
-1217
lines changed

library/std/src/backtrace.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,7 @@ impl Backtrace {
325325
// Capture a backtrace which start just before the function addressed by
326326
// `ip`
327327
fn create(ip: usize) -> Backtrace {
328-
// SAFETY: We don't attempt to lock this reentrantly.
329-
let _lock = unsafe { lock() };
328+
let _lock = lock();
330329
let mut frames = Vec::new();
331330
let mut actual_start = None;
332331
unsafe {
@@ -469,8 +468,7 @@ impl Capture {
469468
// Use the global backtrace lock to synchronize this as it's a
470469
// requirement of the `backtrace` crate, and then actually resolve
471470
// everything.
472-
// SAFETY: We don't attempt to lock this reentrantly.
473-
let _lock = unsafe { lock() };
471+
let _lock = lock();
474472
for frame in self.frames.iter_mut() {
475473
let symbols = &mut frame.symbols;
476474
let frame = match &frame.frame {

library/std/src/io/stdio.rs

+37-37
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::io::prelude::*;
88
use crate::cell::{Cell, RefCell};
99
use crate::fmt;
1010
use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
11-
use crate::pin::Pin;
1211
use crate::sync::atomic::{AtomicBool, Ordering};
1312
use crate::sync::{Arc, Mutex, MutexGuard, OnceLock};
1413
use crate::sys::stdio;
@@ -526,7 +525,7 @@ pub struct Stdout {
526525
// FIXME: this should be LineWriter or BufWriter depending on the state of
527526
// stdout (tty or not). Note that if this is not line buffered it
528527
// should also flush-on-panic or some form of flush-on-abort.
529-
inner: Pin<&'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
528+
inner: &'static ReentrantMutex<RefCell<Option<LineWriter<StdoutRaw>>>>,
530529
}
531530

532531
/// A locked reference to the [`Stdout`] handle.
@@ -548,10 +547,11 @@ pub struct Stdout {
548547
#[must_use = "if unused stdout will immediately unlock"]
549548
#[stable(feature = "rust1", since = "1.0.0")]
550549
pub struct StdoutLock<'a> {
551-
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
550+
inner: ReentrantMutexGuard<'a, RefCell<Option<LineWriter<StdoutRaw>>>>,
552551
}
553552

554-
static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
553+
static STDOUT: ReentrantMutex<RefCell<Option<LineWriter<StdoutRaw>>>> =
554+
ReentrantMutex::new(RefCell::new(None));
555555

556556
/// Constructs a new handle to the standard output of the current process.
557557
///
@@ -602,25 +602,18 @@ static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLo
602602
#[must_use]
603603
#[stable(feature = "rust1", since = "1.0.0")]
604604
pub fn stdout() -> Stdout {
605-
Stdout {
606-
inner: Pin::static_ref(&STDOUT).get_or_init_pin(
607-
|| unsafe { ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))) },
608-
|mutex| unsafe { mutex.init() },
609-
),
610-
}
605+
Stdout { inner: &STDOUT }
611606
}
612607

613608
pub fn cleanup() {
614-
if let Some(instance) = STDOUT.get() {
615-
// Flush the data and disable buffering during shutdown
616-
// by replacing the line writer by one with zero
617-
// buffering capacity.
618-
// We use try_lock() instead of lock(), because someone
619-
// might have leaked a StdoutLock, which would
620-
// otherwise cause a deadlock here.
621-
if let Some(lock) = Pin::static_ref(instance).try_lock() {
622-
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
623-
}
609+
// Flush the data and disable buffering during shutdown
610+
// by replacing the line writer by one with zero
611+
// buffering capacity.
612+
// We use try_lock() instead of lock(), because someone
613+
// might have leaked a StdoutLock, which would
614+
// otherwise cause a deadlock here.
615+
if let Some(lock) = STDOUT.try_lock() {
616+
*lock.borrow_mut() = Some(LineWriter::with_capacity(0, stdout_raw()));
624617
}
625618
}
626619

@@ -670,7 +663,7 @@ impl Write for Stdout {
670663
}
671664
#[inline]
672665
fn is_write_vectored(&self) -> bool {
673-
io::Write::is_write_vectored(&&*self)
666+
stdout_raw().is_write_vectored()
674667
}
675668
fn flush(&mut self) -> io::Result<()> {
676669
(&*self).flush()
@@ -696,7 +689,7 @@ impl Write for &Stdout {
696689
}
697690
#[inline]
698691
fn is_write_vectored(&self) -> bool {
699-
self.lock().is_write_vectored()
692+
stdout_raw().is_write_vectored()
700693
}
701694
fn flush(&mut self) -> io::Result<()> {
702695
self.lock().flush()
@@ -712,26 +705,37 @@ impl Write for &Stdout {
712705
}
713706
}
714707

708+
impl StdoutLock<'_> {
709+
#[inline]
710+
fn with_inner<F, R>(&mut self, f: F) -> R
711+
where
712+
F: FnOnce(&mut LineWriter<StdoutRaw>) -> R,
713+
{
714+
let mut inner = self.inner.borrow_mut();
715+
f(inner.get_or_insert_with(|| LineWriter::new(stdout_raw())))
716+
}
717+
}
718+
715719
#[stable(feature = "rust1", since = "1.0.0")]
716720
impl Write for StdoutLock<'_> {
717721
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
718-
self.inner.borrow_mut().write(buf)
722+
self.with_inner(|stdout| stdout.write(buf))
719723
}
720724
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
721-
self.inner.borrow_mut().write_vectored(bufs)
725+
self.with_inner(|stdout| stdout.write_vectored(bufs))
722726
}
723727
#[inline]
724728
fn is_write_vectored(&self) -> bool {
725-
self.inner.borrow_mut().is_write_vectored()
729+
stdout_raw().is_write_vectored()
726730
}
727731
fn flush(&mut self) -> io::Result<()> {
728-
self.inner.borrow_mut().flush()
732+
self.with_inner(|stdout| stdout.flush())
729733
}
730734
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
731-
self.inner.borrow_mut().write_all(buf)
735+
self.with_inner(|stdout| stdout.write_all(buf))
732736
}
733737
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
734-
self.inner.borrow_mut().write_all_vectored(bufs)
738+
self.with_inner(|stdout| stdout.write_all_vectored(bufs))
735739
}
736740
}
737741

@@ -761,7 +765,7 @@ impl fmt::Debug for StdoutLock<'_> {
761765
/// standard library or via raw Windows API calls, will fail.
762766
#[stable(feature = "rust1", since = "1.0.0")]
763767
pub struct Stderr {
764-
inner: Pin<&'static ReentrantMutex<RefCell<StderrRaw>>>,
768+
inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
765769
}
766770

767771
/// A locked reference to the [`Stderr`] handle.
@@ -834,16 +838,12 @@ pub struct StderrLock<'a> {
834838
#[stable(feature = "rust1", since = "1.0.0")]
835839
pub fn stderr() -> Stderr {
836840
// Note that unlike `stdout()` we don't use `at_exit` here to register a
837-
// destructor. Stderr is not buffered , so there's no need to run a
841+
// destructor. Stderr is not buffered, so there's no need to run a
838842
// destructor for flushing the buffer
839-
static INSTANCE: OnceLock<ReentrantMutex<RefCell<StderrRaw>>> = OnceLock::new();
843+
static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
844+
ReentrantMutex::new(RefCell::new(stderr_raw()));
840845

841-
Stderr {
842-
inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
843-
|| unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) },
844-
|mutex| unsafe { mutex.init() },
845-
),
846-
}
846+
Stderr { inner: &INSTANCE }
847847
}
848848

849849
impl Stderr {

library/std/src/panicking.rs

+46-78
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ use crate::intrinsics;
1818
use crate::mem::{self, ManuallyDrop};
1919
use crate::process;
2020
use crate::sync::atomic::{AtomicBool, Ordering};
21+
use crate::sync::{PoisonError, RwLock};
2122
use crate::sys::stdio::panic_output;
2223
use crate::sys_common::backtrace;
23-
use crate::sys_common::rwlock::StaticRwLock;
2424
use crate::sys_common::thread_info;
2525
use crate::thread;
2626

@@ -71,20 +71,31 @@ extern "C" fn __rust_foreign_exception() -> ! {
7171
rtabort!("Rust cannot catch foreign exceptions");
7272
}
7373

74-
#[derive(Copy, Clone)]
7574
enum Hook {
7675
Default,
77-
Custom(*mut (dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send)),
76+
Custom(Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>),
7877
}
7978

8079
impl Hook {
8180
fn custom(f: impl Fn(&PanicInfo<'_>) + 'static + Sync + Send) -> Self {
82-
Self::Custom(Box::into_raw(Box::new(f)))
81+
Self::Custom(Box::new(f))
82+
}
83+
84+
fn into_box(self) -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
85+
match self {
86+
Hook::Default => Box::new(default_hook),
87+
Hook::Custom(hook) => hook,
88+
}
8389
}
8490
}
8591

86-
static HOOK_LOCK: StaticRwLock = StaticRwLock::new();
87-
static mut HOOK: Hook = Hook::Default;
92+
impl Default for Hook {
93+
fn default() -> Hook {
94+
Hook::Default
95+
}
96+
}
97+
98+
static HOOK: RwLock<Hook> = RwLock::new(Hook::Default);
8899

89100
/// Registers a custom panic hook, replacing any that was previously registered.
90101
///
@@ -125,24 +136,7 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
125136
panic!("cannot modify the panic hook from a panicking thread");
126137
}
127138

128-
// SAFETY:
129-
//
130-
// - `HOOK` can only be modified while holding write access to `HOOK_LOCK`.
131-
// - The argument of `Box::from_raw` is always a valid pointer that was created using
132-
// `Box::into_raw`.
133-
unsafe {
134-
let guard = HOOK_LOCK.write();
135-
let old_hook = HOOK;
136-
HOOK = Hook::Custom(Box::into_raw(hook));
137-
drop(guard);
138-
139-
if let Hook::Custom(ptr) = old_hook {
140-
#[allow(unused_must_use)]
141-
{
142-
Box::from_raw(ptr);
143-
}
144-
}
145-
}
139+
*HOOK.write().unwrap_or_else(PoisonError::into_inner) = Hook::custom(hook);
146140
}
147141

148142
/// Unregisters the current panic hook, returning it.
@@ -179,22 +173,11 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
179173
panic!("cannot modify the panic hook from a panicking thread");
180174
}
181175

182-
// SAFETY:
183-
//
184-
// - `HOOK` can only be modified while holding write access to `HOOK_LOCK`.
185-
// - The argument of `Box::from_raw` is always a valid pointer that was created using
186-
// `Box::into_raw`.
187-
unsafe {
188-
let guard = HOOK_LOCK.write();
189-
let hook = HOOK;
190-
HOOK = Hook::Default;
191-
drop(guard);
176+
let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
177+
let old_hook = mem::take(&mut *hook);
178+
drop(hook);
192179

193-
match hook {
194-
Hook::Default => Box::new(default_hook),
195-
Hook::Custom(ptr) => Box::from_raw(ptr),
196-
}
197-
}
180+
old_hook.into_box()
198181
}
199182

200183
/// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with
@@ -240,24 +223,10 @@ where
240223
panic!("cannot modify the panic hook from a panicking thread");
241224
}
242225

243-
// SAFETY:
244-
//
245-
// - `HOOK` can only be modified while holding write access to `HOOK_LOCK`.
246-
// - The argument of `Box::from_raw` is always a valid pointer that was created using
247-
// `Box::into_raw`.
248-
unsafe {
249-
let guard = HOOK_LOCK.write();
250-
let old_hook = HOOK;
251-
HOOK = Hook::Default;
252-
253-
let prev = match old_hook {
254-
Hook::Default => Box::new(default_hook),
255-
Hook::Custom(ptr) => Box::from_raw(ptr),
256-
};
257-
258-
HOOK = Hook::custom(move |info| hook_fn(&prev, info));
259-
drop(guard);
260-
}
226+
let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
227+
let old_hook = mem::take(&mut *hook);
228+
let prev = old_hook.into_box();
229+
*hook = Hook::custom(move |info| hook_fn(&prev, info));
261230
}
262231

263232
fn default_hook(info: &PanicInfo<'_>) {
@@ -682,27 +651,26 @@ fn rust_panic_with_hook(
682651
crate::sys::abort_internal();
683652
}
684653

685-
unsafe {
686-
let mut info = PanicInfo::internal_constructor(message, location, can_unwind);
687-
let _guard = HOOK_LOCK.read();
688-
match HOOK {
689-
// Some platforms (like wasm) know that printing to stderr won't ever actually
690-
// print anything, and if that's the case we can skip the default
691-
// hook. Since string formatting happens lazily when calling `payload`
692-
// methods, this means we avoid formatting the string at all!
693-
// (The panic runtime might still call `payload.take_box()` though and trigger
694-
// formatting.)
695-
Hook::Default if panic_output().is_none() => {}
696-
Hook::Default => {
697-
info.set_payload(payload.get());
698-
default_hook(&info);
699-
}
700-
Hook::Custom(ptr) => {
701-
info.set_payload(payload.get());
702-
(*ptr)(&info);
703-
}
704-
};
705-
}
654+
let mut info = PanicInfo::internal_constructor(message, location, can_unwind);
655+
let hook = HOOK.read().unwrap_or_else(PoisonError::into_inner);
656+
match *hook {
657+
// Some platforms (like wasm) know that printing to stderr won't ever actually
658+
// print anything, and if that's the case we can skip the default
659+
// hook. Since string formatting happens lazily when calling `payload`
660+
// methods, this means we avoid formatting the string at all!
661+
// (The panic runtime might still call `payload.take_box()` though and trigger
662+
// formatting.)
663+
Hook::Default if panic_output().is_none() => {}
664+
Hook::Default => {
665+
info.set_payload(payload.get());
666+
default_hook(&info);
667+
}
668+
Hook::Custom(ref hook) => {
669+
info.set_payload(payload.get());
670+
hook(&info);
671+
}
672+
};
673+
drop(hook);
706674

707675
if panics > 1 || !can_unwind {
708676
// If a thread panics while it's already unwinding then we

library/std/src/sync/condvar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod tests;
33

44
use crate::fmt;
55
use crate::sync::{mutex, poison, LockResult, MutexGuard, PoisonError};
6-
use crate::sys_common::condvar as sys;
6+
use crate::sys::locks as sys;
77
use crate::time::{Duration, Instant};
88

99
/// A type indicating whether a timed wait on a condition variable returned

0 commit comments

Comments
 (0)