diff options
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/stdio.rs | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 31b881bebf0..d6a9778ced2 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -16,11 +16,12 @@ use cmp; use fmt; use io::lazy::Lazy; use io::{self, BufReader, LineWriter}; +use libc; use sync::{Arc, Mutex, MutexGuard}; use sys::stdio; use sys_common::io::{read_to_end_uninitialized}; use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; -use libc; +use thread::LocalKeyState; /// Stdout used by print! and println! macros thread_local! { @@ -576,14 +577,31 @@ pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> { issue = "0")] #[doc(hidden)] pub fn _print(args: fmt::Arguments) { - let result = LOCAL_STDOUT.with(|s| { - if s.borrow_state() == BorrowState::Unused { - if let Some(w) = s.borrow_mut().as_mut() { - return w.write_fmt(args); - } + // As an implementation of the `println!` macro, we want to try our best to + // not panic wherever possible and get the output somewhere. There are + // currently two possible vectors for panics we take care of here: + // + // 1. If the TLS key for the local stdout has been destroyed, accessing it + // would cause a panic. Note that we just lump in the uninitialized case + // here for convenience, we're not trying to avoid a panic. + // 2. If the local stdout is currently in use (e.g. we're in the middle of + // already printing) then accessing again would cause a panic. + // + // If, however, the actual I/O causes an error, we do indeed panic. + let result = match LOCAL_STDOUT.state() { + LocalKeyState::Uninitialized | + LocalKeyState::Destroyed => stdout().write_fmt(args), + LocalKeyState::Valid => { + LOCAL_STDOUT.with(|s| { + if s.borrow_state() == BorrowState::Unused { + if let Some(w) = s.borrow_mut().as_mut() { + return w.write_fmt(args); + } + } + stdout().write_fmt(args) + }) } - stdout().write_fmt(args) - }); + }; if let Err(e) = result { panic!("failed printing to stdout: {}", e); } |
