@@ -17,7 +17,7 @@ use io::{self, BufReader, LineWriter};
17
17
use sync:: { Arc , Mutex , MutexGuard } ;
18
18
use sys:: stdio;
19
19
use sys_common:: remutex:: { ReentrantMutex , ReentrantMutexGuard } ;
20
- use thread:: LocalKeyState ;
20
+ use thread:: { LocalKey , LocalKeyState } ;
21
21
22
22
/// Stdout used by print! and println! macros
23
23
thread_local ! {
@@ -659,75 +659,54 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
659
659
} )
660
660
}
661
661
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 ( ) {
679
677
LocalKeyState :: Uninitialized |
680
- LocalKeyState :: Destroyed => stdout ( ) . write_fmt ( args) ,
678
+ LocalKeyState :: Destroyed => global_s ( ) . write_fmt ( args) ,
681
679
LocalKeyState :: Valid => {
682
- LOCAL_STDOUT . with ( |s| {
680
+ local_s . with ( |s| {
683
681
if let Ok ( mut borrowed) = s. try_borrow_mut ( ) {
684
682
if let Some ( w) = borrowed. as_mut ( ) {
685
683
return w. write_fmt ( args) ;
686
684
}
687
685
}
688
- stdout ( ) . write_fmt ( args)
686
+ global_s ( ) . write_fmt ( args)
689
687
} )
690
688
}
691
689
} ;
692
690
if let Err ( e) = result {
693
- panic ! ( "failed printing to stdout : {}" , e) ;
691
+ panic ! ( "failed printing to {} : {}" , label , e) ;
694
692
}
695
693
}
696
694
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
+
697
703
#[ unstable( feature = "eprint_internal" ,
698
704
reason = "implementation detail which may disappear or be replaced at any time" ,
699
705
issue = "0" ) ]
700
706
#[ doc( hidden) ]
701
707
pub 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.
713
708
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" ) ;
731
710
}
732
711
733
712
#[ cfg( test) ]
0 commit comments