@@ -10,22 +10,24 @@ use crate::fmt;
1010use crate :: io:: { self , BufReader , Initializer , IoSlice , IoSliceMut , LineWriter } ;
1111use crate :: lazy:: SyncOnceCell ;
1212use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
13- use crate :: sync:: { Mutex , MutexGuard } ;
13+ use crate :: sync:: { Arc , Mutex , MutexGuard } ;
1414use crate :: sys:: stdio;
1515use crate :: sys_common;
1616use crate :: sys_common:: remutex:: { ReentrantMutex , ReentrantMutexGuard } ;
1717use crate :: thread:: LocalKey ;
1818
19+ type LocalStream = Arc < Mutex < dyn Write + Send > > ;
20+
1921thread_local ! {
2022 /// Used by the test crate to capture the output of the print! and println! macros.
21- static LOCAL_STDOUT : RefCell <Option <Box <dyn LocalOutput > >> = {
23+ static LOCAL_STDOUT : RefCell <Option <LocalStream >> = {
2224 RefCell :: new( None )
2325 }
2426}
2527
2628thread_local ! {
2729 /// Used by the test crate to capture the output of the eprint! and eprintln! macros, and panics.
28- static LOCAL_STDERR : RefCell <Option <Box <dyn LocalOutput > >> = {
30+ static LOCAL_STDERR : RefCell <Option <LocalStream >> = {
2931 RefCell :: new( None )
3032 }
3133}
@@ -888,18 +890,6 @@ impl fmt::Debug for StderrLock<'_> {
888890 }
889891}
890892
891- /// A writer than can be cloned to new threads.
892- #[ unstable(
893- feature = "set_stdio" ,
894- reason = "this trait may disappear completely or be replaced \
895- with a more general mechanism",
896- issue = "none"
897- ) ]
898- #[ doc( hidden) ]
899- pub trait LocalOutput : Write + Send {
900- fn clone_box ( & self ) -> Box < dyn LocalOutput > ;
901- }
902-
903893/// Resets the thread-local stderr handle to the specified writer
904894///
905895/// This will replace the current thread's stderr handle, returning the old
@@ -915,18 +905,17 @@ pub trait LocalOutput: Write + Send {
915905 issue = "none"
916906) ]
917907#[ doc( hidden) ]
918- pub fn set_panic ( sink : Option < Box < dyn LocalOutput > > ) -> Option < Box < dyn LocalOutput > > {
908+ pub fn set_panic ( sink : Option < LocalStream > ) -> Option < LocalStream > {
919909 use crate :: mem;
920910 if sink. is_none ( ) && !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
921911 // LOCAL_STDERR is definitely None since LOCAL_STREAMS is false.
922912 return None ;
923913 }
924- let s = LOCAL_STDERR . with ( move |slot| mem :: replace ( & mut * slot . borrow_mut ( ) , sink ) ) . and_then (
925- | mut s| {
926- let _ = s. flush ( ) ;
914+ let s =
915+ LOCAL_STDERR . with ( move |slot| mem :: replace ( & mut * slot . borrow_mut ( ) , sink ) ) . and_then ( | s| {
916+ let _ = s. lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) . flush ( ) ;
927917 Some ( s)
928- } ,
929- ) ;
918+ } ) ;
930919 LOCAL_STREAMS . store ( true , Ordering :: Relaxed ) ;
931920 s
932921}
@@ -946,35 +935,29 @@ pub fn set_panic(sink: Option<Box<dyn LocalOutput>>) -> Option<Box<dyn LocalOutp
946935 issue = "none"
947936) ]
948937#[ doc( hidden) ]
949- pub fn set_print ( sink : Option < Box < dyn LocalOutput > > ) -> Option < Box < dyn LocalOutput > > {
938+ pub fn set_print ( sink : Option < LocalStream > ) -> Option < LocalStream > {
950939 use crate :: mem;
951940 if sink. is_none ( ) && !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
952941 // LOCAL_STDOUT is definitely None since LOCAL_STREAMS is false.
953942 return None ;
954943 }
955- let s = LOCAL_STDOUT . with ( move |slot| mem :: replace ( & mut * slot . borrow_mut ( ) , sink ) ) . and_then (
956- | mut s| {
957- let _ = s. flush ( ) ;
944+ let s =
945+ LOCAL_STDOUT . with ( move |slot| mem :: replace ( & mut * slot . borrow_mut ( ) , sink ) ) . and_then ( | s| {
946+ let _ = s. lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) . flush ( ) ;
958947 Some ( s)
959- } ,
960- ) ;
948+ } ) ;
961949 LOCAL_STREAMS . store ( true , Ordering :: Relaxed ) ;
962950 s
963951}
964952
965- pub ( crate ) fn clone_io ( ) -> ( Option < Box < dyn LocalOutput > > , Option < Box < dyn LocalOutput > > ) {
953+ pub ( crate ) fn clone_io ( ) -> ( Option < LocalStream > , Option < LocalStream > ) {
966954 // Don't waste time when LOCAL_{STDOUT,STDERR} are definitely None.
967955 if !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
968956 return ( None , None ) ;
969957 }
970958
971959 LOCAL_STDOUT . with ( |stdout| {
972- LOCAL_STDERR . with ( |stderr| {
973- (
974- stdout. borrow ( ) . as_ref ( ) . map ( |o| o. clone_box ( ) ) ,
975- stderr. borrow ( ) . as_ref ( ) . map ( |o| o. clone_box ( ) ) ,
976- )
977- } )
960+ LOCAL_STDERR . with ( |stderr| ( stdout. borrow ( ) . clone ( ) , stderr. borrow ( ) . clone ( ) ) )
978961 } )
979962}
980963
@@ -990,7 +973,7 @@ pub(crate) fn clone_io() -> (Option<Box<dyn LocalOutput>>, Option<Box<dyn LocalO
990973/// However, if the actual I/O causes an error, this function does panic.
991974fn print_to < T > (
992975 args : fmt:: Arguments < ' _ > ,
993- local_s : & ' static LocalKey < RefCell < Option < Box < dyn LocalOutput > > > > ,
976+ local_s : & ' static LocalKey < RefCell < Option < LocalStream > > > ,
994977 global_s : fn ( ) -> T ,
995978 label : & str ,
996979) where
@@ -1005,8 +988,8 @@ fn print_to<T>(
1005988 // our printing recursively panics/prints, so the recursive
1006989 // panic/print goes to the global sink instead of our local sink.
1007990 let prev = s. borrow_mut ( ) . take ( ) ;
1008- if let Some ( mut w) = prev {
1009- let result = w. write_fmt ( args) ;
991+ if let Some ( w) = prev {
992+ let result = w. lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) . write_fmt ( args) ;
1010993 * s. borrow_mut ( ) = Some ( w) ;
1011994 return result;
1012995 }
0 commit comments