@@ -17,7 +17,7 @@ use io::{self, BufReader, LineWriter};
1717use  sync:: { Arc ,  Mutex ,  MutexGuard } ; 
1818use  sys:: stdio; 
1919use  sys_common:: remutex:: { ReentrantMutex ,  ReentrantMutexGuard } ; 
20- use  thread:: LocalKeyState ; 
20+ use  thread:: { LocalKey ,   LocalKeyState } ; 
2121
2222/// Stdout used by print! and println! macros 
2323thread_local !  { 
@@ -659,75 +659,54 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
659659    } ) 
660660} 
661661
662- #[ unstable( feature = "print" ,  
663-            reason = "implementation detail which may disappear or be replaced at any time" ,  
664-            issue = "0" ) ]  
665- #[ doc( hidden) ]  
666- pub  fn  _print ( args :  fmt:: Arguments )  { 
667-     // As an implementation of the `println!` macro, we want to try our best to 
668-     // not panic wherever possible and get the output somewhere. There are 
669-     // currently two possible vectors for panics we take care of here: 
670-     // 
671-     // 1. If the TLS key for the local stdout has been destroyed, accessing it 
672-     //    would cause a panic. Note that we just lump in the uninitialized case 
673-     //    here for convenience, we're not trying to avoid a panic. 
674-     // 2. If the local stdout is currently in use (e.g. we're in the middle of 
675-     //    already printing) then accessing again would cause a panic. 
676-     // 
677-     // If, however, the actual I/O causes an error, we do indeed panic. 
678-     let  result = match  LOCAL_STDOUT . state ( )  { 
662+ /// Write `args` to output stream `local_s` if possible, `global_s` 
663+ /// otherwise. `label` identifies the stream in a panic message. 
664+ /// 
665+ /// This function is used to print error messages, so it takes extra 
666+ /// care to avoid causing a panic when `local_stream` is unusable. 
667+ /// For instance, if the TLS key for the local stream is uninitialized 
668+ /// or already destroyed, or if the local stream is locked by another 
669+ /// thread, it will just fall back to the global stream. 
670+ /// 
671+ /// However, if the actual I/O causes an error, this function does panic. 
672+ fn  print_to < T > ( args :  fmt:: Arguments , 
673+                local_s :  & ' static  LocalKey < RefCell < Option < Box < Write +Send > > > > , 
674+                global_s :  fn ( )  -> T , 
675+                label :  & str )  where  T :  Write  { 
676+     let  result = match  local_s. state ( )  { 
679677        LocalKeyState :: Uninitialized  |
680-         LocalKeyState :: Destroyed  => stdout ( ) . write_fmt ( args) , 
678+         LocalKeyState :: Destroyed  => global_s ( ) . write_fmt ( args) , 
681679        LocalKeyState :: Valid  => { 
682-             LOCAL_STDOUT . with ( |s| { 
680+             local_s . with ( |s| { 
683681                if  let  Ok ( mut  borrowed)  = s. try_borrow_mut ( )  { 
684682                    if  let  Some ( w)  = borrowed. as_mut ( )  { 
685683                        return  w. write_fmt ( args) ; 
686684                    } 
687685                } 
688-                 stdout ( ) . write_fmt ( args) 
686+                 global_s ( ) . write_fmt ( args) 
689687            } ) 
690688        } 
691689    } ; 
692690    if  let  Err ( e)  = result { 
693-         panic ! ( "failed printing to stdout : {}" ,  e) ; 
691+         panic ! ( "failed printing to {} : {}" ,  label ,  e) ; 
694692    } 
695693} 
696694
695+ #[ unstable( feature = "print" ,  
696+            reason = "implementation detail which may disappear or be replaced at any time" ,  
697+            issue = "0" ) ]  
698+ #[ doc( hidden) ]  
699+ pub  fn  _print ( args :  fmt:: Arguments )  { 
700+     print_to ( args,  & LOCAL_STDOUT ,  stdout,  "stdout" ) ; 
701+ } 
702+ 
697703#[ unstable( feature = "eprint_internal" ,  
698704           reason = "implementation detail which may disappear or be replaced at any time" ,  
699705           issue = "0" ) ]  
700706#[ doc( hidden) ]  
701707pub  fn  _eprint ( args :  fmt:: Arguments )  { 
702-     // As an implementation of the `eprintln!` macro, we want to try our best to 
703-     // not panic wherever possible and get the output somewhere. There are 
704-     // currently two possible vectors for panics we take care of here: 
705-     // 
706-     // 1. If the TLS key for the local stderr has been destroyed, accessing it 
707-     //    would cause a panic. Note that we just lump in the uninitialized case 
708-     //    here for convenience, we're not trying to avoid a panic. 
709-     // 2. If the local stderr is currently in use (e.g. we're in the middle of 
710-     //    already printing) then accessing again would cause a panic. 
711-     // 
712-     // If, however, the actual I/O causes an error, we do indeed panic. 
713708    use  panicking:: LOCAL_STDERR ; 
714-     let  result = match  LOCAL_STDERR . state ( )  { 
715-         LocalKeyState :: Uninitialized  |
716-         LocalKeyState :: Destroyed  => stderr ( ) . write_fmt ( args) , 
717-         LocalKeyState :: Valid  => { 
718-             LOCAL_STDERR . with ( |s| { 
719-                 if  let  Ok ( mut  borrowed)  = s. try_borrow_mut ( )  { 
720-                     if  let  Some ( w)  = borrowed. as_mut ( )  { 
721-                         return  w. write_fmt ( args) ; 
722-                     } 
723-                 } 
724-                 stderr ( ) . write_fmt ( args) 
725-             } ) 
726-         } 
727-     } ; 
728-     if  let  Err ( e)  = result { 
729-         panic ! ( "failed printing to stderr: {}" ,  e) ; 
730-     } 
709+     print_to ( args,  & LOCAL_STDERR ,  stderr,  "stderr" ) ; 
731710} 
732711
733712#[ cfg( test) ]  
0 commit comments