]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/stdio.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.git] / src / libstd / io / stdio.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use io::prelude::*;
12
13 use cell::{RefCell, BorrowState};
14 use fmt;
15 use io::lazy::Lazy;
16 use io::{self, BufReader, LineWriter};
17 use sync::{Arc, Mutex, MutexGuard};
18 use sys::stdio;
19 use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
20 use thread::LocalKeyState;
21
22 /// Stdout used by print! and println! macros
23 thread_local! {
24     static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = {
25         RefCell::new(None)
26     }
27 }
28
29 /// A handle to a raw instance of the standard input stream of this process.
30 ///
31 /// This handle is not synchronized or buffered in any fashion. Constructed via
32 /// the `std::io::stdio::stdin_raw` function.
33 struct StdinRaw(stdio::Stdin);
34
35 /// A handle to a raw instance of the standard output stream of this process.
36 ///
37 /// This handle is not synchronized or buffered in any fashion. Constructed via
38 /// the `std::io::stdio::stdout_raw` function.
39 struct StdoutRaw(stdio::Stdout);
40
41 /// A handle to a raw instance of the standard output stream of this process.
42 ///
43 /// This handle is not synchronized or buffered in any fashion. Constructed via
44 /// the `std::io::stdio::stderr_raw` function.
45 struct StderrRaw(stdio::Stderr);
46
47 /// Constructs a new raw handle to the standard input of this process.
48 ///
49 /// The returned handle does not interact with any other handles created nor
50 /// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
51 /// handles is **not** available to raw handles returned from this function.
52 ///
53 /// The returned handle has no external synchronization or buffering.
54 fn stdin_raw() -> io::Result<StdinRaw> { stdio::Stdin::new().map(StdinRaw) }
55
56 /// Constructs a new raw handle to the standard output stream of this process.
57 ///
58 /// The returned handle does not interact with any other handles created nor
59 /// handles returned by `std::io::stdout`. Note that data is buffered by the
60 /// `std::io::stdout` handles so writes which happen via this raw handle may
61 /// appear before previous writes.
62 ///
63 /// The returned handle has no external synchronization or buffering layered on
64 /// top.
65 fn stdout_raw() -> io::Result<StdoutRaw> { stdio::Stdout::new().map(StdoutRaw) }
66
67 /// Constructs a new raw handle to the standard error stream of this process.
68 ///
69 /// The returned handle does not interact with any other handles created nor
70 /// handles returned by `std::io::stderr`.
71 ///
72 /// The returned handle has no external synchronization or buffering layered on
73 /// top.
74 fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) }
75
76 impl Read for StdinRaw {
77     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
78     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
79         self.0.read_to_end(buf)
80     }
81 }
82 impl Write for StdoutRaw {
83     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
84     fn flush(&mut self) -> io::Result<()> { Ok(()) }
85 }
86 impl Write for StderrRaw {
87     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
88     fn flush(&mut self) -> io::Result<()> { Ok(()) }
89 }
90
91 enum Maybe<T> {
92     Real(T),
93     Fake,
94 }
95
96 impl<W: io::Write> io::Write for Maybe<W> {
97     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
98         match *self {
99             Maybe::Real(ref mut w) => handle_ebadf(w.write(buf), buf.len()),
100             Maybe::Fake => Ok(buf.len())
101         }
102     }
103
104     fn flush(&mut self) -> io::Result<()> {
105         match *self {
106             Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
107             Maybe::Fake => Ok(())
108         }
109     }
110 }
111
112 impl<R: io::Read> io::Read for Maybe<R> {
113     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
114         match *self {
115             Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), 0),
116             Maybe::Fake => Ok(0)
117         }
118     }
119     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
120         match *self {
121             Maybe::Real(ref mut r) => handle_ebadf(r.read_to_end(buf), 0),
122             Maybe::Fake => Ok(0)
123         }
124     }
125 }
126
127 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
128     #[cfg(windows)]
129     const ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32;
130     #[cfg(not(windows))]
131     const ERR: i32 = ::libc::EBADF as i32;
132
133     match r {
134         Err(ref e) if e.raw_os_error() == Some(ERR) => Ok(default),
135         r => r
136     }
137 }
138
139 /// A handle to the standard input stream of a process.
140 ///
141 /// Each handle is a shared reference to a global buffer of input data to this
142 /// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
143 /// (e.g. `.lines()`). Reads to this handle are otherwise locked with respect
144 /// to other reads.
145 ///
146 /// This handle implements the `Read` trait, but beware that concurrent reads
147 /// of `Stdin` must be executed with care.
148 ///
149 /// Created by the [`io::stdin`] method.
150 ///
151 /// [`io::stdin`]: fn.stdin.html
152 /// [`BufRead`]: trait.BufRead.html
153 #[stable(feature = "rust1", since = "1.0.0")]
154 pub struct Stdin {
155     inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
156 }
157
158 /// A locked reference to the `Stdin` handle.
159 ///
160 /// This handle implements both the [`Read`] and [`BufRead`] traits, and
161 /// is constructed via the [`Stdin::lock`] method.
162 ///
163 /// [`Read`]: trait.Read.html
164 /// [`BufRead`]: trait.BufRead.html
165 /// [`Stdin::lock`]: struct.Stdin.html#method.lock
166 #[stable(feature = "rust1", since = "1.0.0")]
167 pub struct StdinLock<'a> {
168     inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
169 }
170
171 /// Constructs a new handle to the standard input of the current process.
172 ///
173 /// Each handle returned is a reference to a shared global buffer whose access
174 /// is synchronized via a mutex. If you need more explicit control over
175 /// locking, see the [`lock() method`][lock].
176 ///
177 /// [lock]: struct.Stdin.html#method.lock
178 ///
179 /// # Examples
180 ///
181 /// Using implicit synchronization:
182 ///
183 /// ```
184 /// use std::io::{self, Read};
185 ///
186 /// # fn foo() -> io::Result<String> {
187 /// let mut buffer = String::new();
188 /// try!(io::stdin().read_to_string(&mut buffer));
189 /// # Ok(buffer)
190 /// # }
191 /// ```
192 ///
193 /// Using explicit synchronization:
194 ///
195 /// ```
196 /// use std::io::{self, Read};
197 ///
198 /// # fn foo() -> io::Result<String> {
199 /// let mut buffer = String::new();
200 /// let stdin = io::stdin();
201 /// let mut handle = stdin.lock();
202 ///
203 /// try!(handle.read_to_string(&mut buffer));
204 /// # Ok(buffer)
205 /// # }
206 /// ```
207 #[stable(feature = "rust1", since = "1.0.0")]
208 pub fn stdin() -> Stdin {
209     static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new(stdin_init);
210     return Stdin {
211         inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
212     };
213
214     fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
215         let stdin = match stdin_raw() {
216             Ok(stdin) => Maybe::Real(stdin),
217             _ => Maybe::Fake
218         };
219
220         // The default buffer capacity is 64k, but apparently windows
221         // doesn't like 64k reads on stdin. See #13304 for details, but the
222         // idea is that on windows we use a slightly smaller buffer that's
223         // been seen to be acceptable.
224         Arc::new(Mutex::new(if cfg!(windows) {
225             BufReader::with_capacity(8 * 1024, stdin)
226         } else {
227             BufReader::new(stdin)
228         }))
229     }
230 }
231
232 impl Stdin {
233     /// Locks this handle to the standard input stream, returning a readable
234     /// guard.
235     ///
236     /// The lock is released when the returned lock goes out of scope. The
237     /// returned guard also implements the [`Read`] and [`BufRead`] traits for
238     /// accessing the underlying data.
239     ///
240     /// [`Read`]: trait.Read.html
241     /// [`BufRead`]: trait.BufRead.html
242     ///
243     /// # Examples
244     ///
245     /// ```
246     /// use std::io::{self, Read};
247     ///
248     /// # fn foo() -> io::Result<String> {
249     /// let mut buffer = String::new();
250     /// let stdin = io::stdin();
251     /// let mut handle = stdin.lock();
252     ///
253     /// try!(handle.read_to_string(&mut buffer));
254     /// # Ok(buffer)
255     /// # }
256     /// ```
257     #[stable(feature = "rust1", since = "1.0.0")]
258     pub fn lock(&self) -> StdinLock {
259         StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
260     }
261
262     /// Locks this handle and reads a line of input into the specified buffer.
263     ///
264     /// For detailed semantics of this method, see the documentation on
265     /// [`BufRead::read_line`].
266     ///
267     /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line
268     ///
269     /// # Examples
270     ///
271     /// ```no_run
272     /// use std::io;
273     ///
274     /// let mut input = String::new();
275     /// match io::stdin().read_line(&mut input) {
276     ///     Ok(n) => {
277     ///         println!("{} bytes read", n);
278     ///         println!("{}", input);
279     ///     }
280     ///     Err(error) => println!("error: {}", error),
281     /// }
282     /// ```
283     ///
284     /// You can run the example one of two ways:
285     ///
286     /// - Pipe some text to it, e.g. `printf foo | path/to/executable`
287     /// - Give it text interactively by running the executable directly,
288     ///   in which case it will wait for the Enter key to be pressed before
289     ///   continuing
290     #[stable(feature = "rust1", since = "1.0.0")]
291     pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
292         self.lock().read_line(buf)
293     }
294 }
295
296 #[stable(feature = "rust1", since = "1.0.0")]
297 impl Read for Stdin {
298     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
299         self.lock().read(buf)
300     }
301     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
302         self.lock().read_to_end(buf)
303     }
304     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
305         self.lock().read_to_string(buf)
306     }
307     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
308         self.lock().read_exact(buf)
309     }
310 }
311
312 #[stable(feature = "rust1", since = "1.0.0")]
313 impl<'a> Read for StdinLock<'a> {
314     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
315         self.inner.read(buf)
316     }
317     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
318         self.inner.read_to_end(buf)
319     }
320 }
321
322 #[stable(feature = "rust1", since = "1.0.0")]
323 impl<'a> BufRead for StdinLock<'a> {
324     fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
325     fn consume(&mut self, n: usize) { self.inner.consume(n) }
326 }
327
328 /// A handle to the global standard output stream of the current process.
329 ///
330 /// Each handle shares a global buffer of data to be written to the standard
331 /// output stream. Access is also synchronized via a lock and explicit control
332 /// over locking is available via the `lock` method.
333 ///
334 /// Created by the [`io::stdout`] method.
335 ///
336 /// [`io::stdout`]: fn.stdout.html
337 #[stable(feature = "rust1", since = "1.0.0")]
338 pub struct Stdout {
339     // FIXME: this should be LineWriter or BufWriter depending on the state of
340     //        stdout (tty or not). Note that if this is not line buffered it
341     //        should also flush-on-panic or some form of flush-on-abort.
342     inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>,
343 }
344
345 /// A locked reference to the `Stdout` handle.
346 ///
347 /// This handle implements the [`Write`] trait, and is constructed via
348 /// the [`Stdout::lock`] method.
349 ///
350 /// [`Write`]: trait.Write.html
351 /// [`Stdout::lock`]: struct.Stdout.html#method.lock
352 #[stable(feature = "rust1", since = "1.0.0")]
353 pub struct StdoutLock<'a> {
354     inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
355 }
356
357 /// Constructs a new handle to the standard output of the current process.
358 ///
359 /// Each handle returned is a reference to a shared global buffer whose access
360 /// is synchronized via a mutex. If you need more explicit control over
361 /// locking, see the [Stdout::lock] method.
362 ///
363 /// [Stdout::lock]: struct.Stdout.html#method.lock
364 ///
365 /// # Examples
366 ///
367 /// Using implicit synchronization:
368 ///
369 /// ```
370 /// use std::io::{self, Write};
371 ///
372 /// # fn foo() -> io::Result<()> {
373 /// try!(io::stdout().write(b"hello world"));
374 ///
375 /// # Ok(())
376 /// # }
377 /// ```
378 ///
379 /// Using explicit synchronization:
380 ///
381 /// ```
382 /// use std::io::{self, Write};
383 ///
384 /// # fn foo() -> io::Result<()> {
385 /// let stdout = io::stdout();
386 /// let mut handle = stdout.lock();
387 ///
388 /// try!(handle.write(b"hello world"));
389 ///
390 /// # Ok(())
391 /// # }
392 /// ```
393 #[stable(feature = "rust1", since = "1.0.0")]
394 pub fn stdout() -> Stdout {
395     static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>
396         = Lazy::new(stdout_init);
397     return Stdout {
398         inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
399     };
400
401     fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
402         let stdout = match stdout_raw() {
403             Ok(stdout) => Maybe::Real(stdout),
404             _ => Maybe::Fake,
405         };
406         Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))))
407     }
408 }
409
410 impl Stdout {
411     /// Locks this handle to the standard output stream, returning a writable
412     /// guard.
413     ///
414     /// The lock is released when the returned lock goes out of scope. The
415     /// returned guard also implements the `Write` trait for writing data.
416     ///
417     /// # Examples
418     ///
419     /// ```
420     /// use std::io::{self, Write};
421     ///
422     /// # fn foo() -> io::Result<()> {
423     /// let stdout = io::stdout();
424     /// let mut handle = stdout.lock();
425     ///
426     /// try!(handle.write(b"hello world"));
427     ///
428     /// # Ok(())
429     /// # }
430     /// ```
431     #[stable(feature = "rust1", since = "1.0.0")]
432     pub fn lock(&self) -> StdoutLock {
433         StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
434     }
435 }
436
437 #[stable(feature = "rust1", since = "1.0.0")]
438 impl Write for Stdout {
439     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
440         self.lock().write(buf)
441     }
442     fn flush(&mut self) -> io::Result<()> {
443         self.lock().flush()
444     }
445     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
446         self.lock().write_all(buf)
447     }
448     fn write_fmt(&mut self, args: fmt::Arguments) -> io::Result<()> {
449         self.lock().write_fmt(args)
450     }
451 }
452 #[stable(feature = "rust1", since = "1.0.0")]
453 impl<'a> Write for StdoutLock<'a> {
454     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
455         self.inner.borrow_mut().write(buf)
456     }
457     fn flush(&mut self) -> io::Result<()> {
458         self.inner.borrow_mut().flush()
459     }
460 }
461
462 /// A handle to the standard error stream of a process.
463 ///
464 /// For more information, see the [`io::stderr`] method.
465 ///
466 /// [`io::stderr`]: fn.stderr.html
467 #[stable(feature = "rust1", since = "1.0.0")]
468 pub struct Stderr {
469     inner: Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>>,
470 }
471
472 /// A locked reference to the `Stderr` handle.
473 ///
474 /// This handle implements the `Write` trait and is constructed via
475 /// the [`Stderr::lock`] method.
476 ///
477 /// [`Stderr::lock`]: struct.Stderr.html#method.lock
478 #[stable(feature = "rust1", since = "1.0.0")]
479 pub struct StderrLock<'a> {
480     inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
481 }
482
483 /// Constructs a new handle to the standard error of the current process.
484 ///
485 /// This handle is not buffered.
486 ///
487 /// # Examples
488 ///
489 /// Using implicit synchronization:
490 ///
491 /// ```
492 /// use std::io::{self, Write};
493 ///
494 /// # fn foo() -> io::Result<()> {
495 /// try!(io::stderr().write(b"hello world"));
496 ///
497 /// # Ok(())
498 /// # }
499 /// ```
500 ///
501 /// Using explicit synchronization:
502 ///
503 /// ```
504 /// use std::io::{self, Write};
505 ///
506 /// # fn foo() -> io::Result<()> {
507 /// let stderr = io::stderr();
508 /// let mut handle = stderr.lock();
509 ///
510 /// try!(handle.write(b"hello world"));
511 ///
512 /// # Ok(())
513 /// # }
514 /// ```
515 #[stable(feature = "rust1", since = "1.0.0")]
516 pub fn stderr() -> Stderr {
517     static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new(stderr_init);
518     return Stderr {
519         inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
520     };
521
522     fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
523         let stderr = match stderr_raw() {
524             Ok(stderr) => Maybe::Real(stderr),
525             _ => Maybe::Fake,
526         };
527         Arc::new(ReentrantMutex::new(RefCell::new(stderr)))
528     }
529 }
530
531 impl Stderr {
532     /// Locks this handle to the standard error stream, returning a writable
533     /// guard.
534     ///
535     /// The lock is released when the returned lock goes out of scope. The
536     /// returned guard also implements the `Write` trait for writing data.
537     ///
538     /// # Examples
539     ///
540     /// ```
541     /// use std::io::{self, Write};
542     ///
543     /// fn foo() -> io::Result<()> {
544     ///     let stderr = io::stderr();
545     ///     let mut handle = stderr.lock();
546     ///
547     ///     try!(handle.write(b"hello world"));
548     ///
549     ///     Ok(())
550     /// }
551     /// ```
552     #[stable(feature = "rust1", since = "1.0.0")]
553     pub fn lock(&self) -> StderrLock {
554         StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
555     }
556 }
557
558 #[stable(feature = "rust1", since = "1.0.0")]
559 impl Write for Stderr {
560     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
561         self.lock().write(buf)
562     }
563     fn flush(&mut self) -> io::Result<()> {
564         self.lock().flush()
565     }
566     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
567         self.lock().write_all(buf)
568     }
569     fn write_fmt(&mut self, args: fmt::Arguments) -> io::Result<()> {
570         self.lock().write_fmt(args)
571     }
572 }
573 #[stable(feature = "rust1", since = "1.0.0")]
574 impl<'a> Write for StderrLock<'a> {
575     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
576         self.inner.borrow_mut().write(buf)
577     }
578     fn flush(&mut self) -> io::Result<()> {
579         self.inner.borrow_mut().flush()
580     }
581 }
582
583 /// Resets the thread-local stderr handle to the specified writer
584 ///
585 /// This will replace the current thread's stderr handle, returning the old
586 /// handle. All future calls to `panic!` and friends will emit their output to
587 /// this specified handle.
588 ///
589 /// Note that this does not need to be called for all new threads; the default
590 /// output handle is to the process's stderr stream.
591 #[unstable(feature = "set_stdio",
592            reason = "this function may disappear completely or be replaced \
593                      with a more general mechanism",
594            issue = "0")]
595 #[doc(hidden)]
596 pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
597     use panicking::LOCAL_STDERR;
598     use mem;
599     LOCAL_STDERR.with(move |slot| {
600         mem::replace(&mut *slot.borrow_mut(), Some(sink))
601     }).and_then(|mut s| {
602         let _ = s.flush();
603         Some(s)
604     })
605 }
606
607 /// Resets the thread-local stdout handle to the specified writer
608 ///
609 /// This will replace the current thread's stdout handle, returning the old
610 /// handle. All future calls to `print!` and friends will emit their output to
611 /// this specified handle.
612 ///
613 /// Note that this does not need to be called for all new threads; the default
614 /// output handle is to the process's stdout stream.
615 #[unstable(feature = "set_stdio",
616            reason = "this function may disappear completely or be replaced \
617                      with a more general mechanism",
618            issue = "0")]
619 #[doc(hidden)]
620 pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
621     use mem;
622     LOCAL_STDOUT.with(move |slot| {
623         mem::replace(&mut *slot.borrow_mut(), Some(sink))
624     }).and_then(|mut s| {
625         let _ = s.flush();
626         Some(s)
627     })
628 }
629
630 #[unstable(feature = "print",
631            reason = "implementation detail which may disappear or be replaced at any time",
632            issue = "0")]
633 #[doc(hidden)]
634 pub fn _print(args: fmt::Arguments) {
635     // As an implementation of the `println!` macro, we want to try our best to
636     // not panic wherever possible and get the output somewhere. There are
637     // currently two possible vectors for panics we take care of here:
638     //
639     // 1. If the TLS key for the local stdout has been destroyed, accessing it
640     //    would cause a panic. Note that we just lump in the uninitialized case
641     //    here for convenience, we're not trying to avoid a panic.
642     // 2. If the local stdout is currently in use (e.g. we're in the middle of
643     //    already printing) then accessing again would cause a panic.
644     //
645     // If, however, the actual I/O causes an error, we do indeed panic.
646     let result = match LOCAL_STDOUT.state() {
647         LocalKeyState::Uninitialized |
648         LocalKeyState::Destroyed => stdout().write_fmt(args),
649         LocalKeyState::Valid => {
650             LOCAL_STDOUT.with(|s| {
651                 if s.borrow_state() == BorrowState::Unused {
652                     if let Some(w) = s.borrow_mut().as_mut() {
653                         return w.write_fmt(args);
654                     }
655                 }
656                 stdout().write_fmt(args)
657             })
658         }
659     };
660     if let Err(e) = result {
661         panic!("failed printing to stdout: {}", e);
662     }
663 }
664
665 #[cfg(test)]
666 mod tests {
667     use thread;
668     use super::*;
669
670     #[test]
671     fn panic_doesnt_poison() {
672         thread::spawn(|| {
673             let _a = stdin();
674             let _a = _a.lock();
675             let _a = stdout();
676             let _a = _a.lock();
677             let _a = stderr();
678             let _a = _a.lock();
679             panic!();
680         }).join().unwrap_err();
681
682         let _a = stdin();
683         let _a = _a.lock();
684         let _a = stdout();
685         let _a = _a.lock();
686         let _a = stderr();
687         let _a = _a.lock();
688     }
689 }