@@ -9,6 +9,7 @@ use crate::cell::RefCell;
99use crate :: fmt;
1010use crate :: io:: { self , BufReader , Initializer , IoSlice , IoSliceMut , LineWriter } ;
1111use crate :: lazy:: SyncOnceCell ;
12+ use crate :: pin:: Pin ;
1213use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
1314use crate :: sync:: { Mutex , MutexGuard } ;
1415use 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> {
548549pub 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" ) ]
700705pub 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
0 commit comments