Skip to content

Commit 88c006b

Browse files
m-ou-seMark-Simulacrum
authored andcommitted
Pin the ReentrantMutexes in sys::io::stdio.
The code before this change misused the ReentrantMutexes, by calling init() on them and moving them afterwards. Now that ReentrantMutex requires Pin for init(), this mistake is no longer easy to make.
1 parent 4137ade commit 88c006b

File tree

2 files changed

+30
-25
lines changed

2 files changed

+30
-25
lines changed

library/std/src/io/stdio.rs

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::cell::RefCell;
99
use crate::fmt;
1010
use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter};
1111
use crate::lazy::SyncOnceCell;
12+
use crate::pin::Pin;
1213
use crate::sync::atomic::{AtomicBool, Ordering};
1314
use crate::sync::{Mutex, MutexGuard};
1415
use crate::sys::stdio;
@@ -488,7 +489,7 @@ pub struct Stdout {
488489
// FIXME: this should be LineWriter or BufWriter depending on the state of
489490
// stdout (tty or not). Note that if this is not line buffered it
490491
// should also flush-on-panic or some form of flush-on-abort.
491-
inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
492+
inner: Pin<&'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
492493
}
493494

494495
/// A locked reference to the `Stdout` handle.
@@ -548,25 +549,29 @@ pub struct StdoutLock<'a> {
548549
pub fn stdout() -> Stdout {
549550
static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> =
550551
SyncOnceCell::new();
552+
553+
fn cleanup() {
554+
if let Some(instance) = INSTANCE.get() {
555+
// Flush the data and disable buffering during shutdown
556+
// by replacing the line writer by one with zero
557+
// buffering capacity.
558+
// We use try_lock() instead of lock(), because someone
559+
// might have leaked a StdoutLock, which would
560+
// otherwise cause a deadlock here.
561+
if let Some(lock) = Pin::static_ref(instance).try_lock() {
562+
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
563+
}
564+
}
565+
}
566+
551567
Stdout {
552-
inner: INSTANCE.get_or_init(|| unsafe {
553-
let _ = sys_common::at_exit(|| {
554-
if let Some(instance) = INSTANCE.get() {
555-
// Flush the data and disable buffering during shutdown
556-
// by replacing the line writer by one with zero
557-
// buffering capacity.
558-
// We use try_lock() instead of lock(), because someone
559-
// might have leaked a StdoutLock, which would
560-
// otherwise cause a deadlock here.
561-
if let Some(lock) = instance.try_lock() {
562-
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
563-
}
564-
}
565-
});
566-
let r = ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())));
567-
r.init();
568-
r
569-
}),
568+
inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
569+
|| unsafe {
570+
let _ = sys_common::at_exit(cleanup);
571+
ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))
572+
},
573+
|mutex| unsafe { mutex.init() },
574+
),
570575
}
571576
}
572577

@@ -698,7 +703,7 @@ impl fmt::Debug for StdoutLock<'_> {
698703
/// an error.
699704
#[stable(feature = "rust1", since = "1.0.0")]
700705
pub struct Stderr {
701-
inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
706+
inner: Pin<&'static ReentrantMutex<RefCell<StderrRaw>>>,
702707
}
703708

704709
/// A locked reference to the `Stderr` handle.
@@ -760,11 +765,10 @@ pub fn stderr() -> Stderr {
760765
static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<StderrRaw>>> = SyncOnceCell::new();
761766

762767
Stderr {
763-
inner: INSTANCE.get_or_init(|| unsafe {
764-
let r = ReentrantMutex::new(RefCell::new(stderr_raw()));
765-
r.init();
766-
r
767-
}),
768+
inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
769+
|| unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) },
770+
|mutex| unsafe { mutex.init() },
771+
),
768772
}
769773
}
770774

library/std/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@
294294
#![feature(panic_info_message)]
295295
#![feature(panic_internals)]
296296
#![feature(panic_unwind)]
297+
#![feature(pin_static_ref)]
297298
#![feature(prelude_import)]
298299
#![feature(ptr_internals)]
299300
#![feature(raw)]

0 commit comments

Comments
 (0)