@@ -9,6 +9,7 @@ use crate::cell::RefCell;
9
9
use crate :: fmt;
10
10
use crate :: io:: { self , BufReader , Initializer , IoSlice , IoSliceMut , LineWriter } ;
11
11
use crate :: lazy:: SyncOnceCell ;
12
+ use crate :: pin:: Pin ;
12
13
use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
13
14
use crate :: sync:: { Mutex , MutexGuard } ;
14
15
use crate :: sys:: stdio;
@@ -488,7 +489,7 @@ pub struct Stdout {
488
489
// FIXME: this should be LineWriter or BufWriter depending on the state of
489
490
// stdout (tty or not). Note that if this is not line buffered it
490
491
// 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 > > > > ,
492
493
}
493
494
494
495
/// A locked reference to the `Stdout` handle.
@@ -548,25 +549,29 @@ pub struct StdoutLock<'a> {
548
549
pub fn stdout ( ) -> Stdout {
549
550
static INSTANCE : SyncOnceCell < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > =
550
551
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
+
551
567
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
+ ) ,
570
575
}
571
576
}
572
577
@@ -698,7 +703,7 @@ impl fmt::Debug for StdoutLock<'_> {
698
703
/// an error.
699
704
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
700
705
pub struct Stderr {
701
- inner : & ' static ReentrantMutex < RefCell < StderrRaw > > ,
706
+ inner : Pin < & ' static ReentrantMutex < RefCell < StderrRaw > > > ,
702
707
}
703
708
704
709
/// A locked reference to the `Stderr` handle.
@@ -760,11 +765,10 @@ pub fn stderr() -> Stderr {
760
765
static INSTANCE : SyncOnceCell < ReentrantMutex < RefCell < StderrRaw > > > = SyncOnceCell :: new ( ) ;
761
766
762
767
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
+ ) ,
768
772
}
769
773
}
770
774
0 commit comments