]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/stdio.rs
Rollup merge of #52019 - michaelwoerister:cross-lto-auto-plugin, r=alexcrichton
[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;
14 use fmt;
15 use io::lazy::Lazy;
16 use io::{self, Initializer, BufReader, LineWriter};
17 use sync::{Arc, Mutex, MutexGuard};
18 use sys::stdio;
19 use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
20 use thread::LocalKey;
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
79     #[inline]
80     unsafe fn initializer(&self) -> Initializer {
81         Initializer::nop()
82     }
83 }
84 impl Write for StdoutRaw {
85     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
86     fn flush(&mut self) -> io::Result<()> { self.0.flush() }
87 }
88 impl Write for StderrRaw {
89     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
90     fn flush(&mut self) -> io::Result<()> { self.0.flush() }
91 }
92
93 enum Maybe<T> {
94     Real(T),
95     Fake,
96 }
97
98 impl<W: io::Write> io::Write for Maybe<W> {
99     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
100         match *self {
101             Maybe::Real(ref mut w) => handle_ebadf(w.write(buf), buf.len()),
102             Maybe::Fake => Ok(buf.len())
103         }
104     }
105
106     fn flush(&mut self) -> io::Result<()> {
107         match *self {
108             Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
109             Maybe::Fake => Ok(())
110         }
111     }
112 }
113
114 impl<R: io::Read> io::Read for Maybe<R> {
115     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
116         match *self {
117             Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), 0),
118             Maybe::Fake => Ok(0)
119         }
120     }
121 }
122
123 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
124     match r {
125         Err(ref e) if stdio::is_ebadf(e) => Ok(default),
126         r => r
127     }
128 }
129
130 /// A handle to the standard input stream of a process.
131 ///
132 /// Each handle is a shared reference to a global buffer of input data to this
133 /// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
134 /// (e.g. `.lines()`). Reads to this handle are otherwise locked with respect
135 /// to other reads.
136 ///
137 /// This handle implements the `Read` trait, but beware that concurrent reads
138 /// of `Stdin` must be executed with care.
139 ///
140 /// Created by the [`io::stdin`] method.
141 ///
142 /// [`io::stdin`]: fn.stdin.html
143 /// [`BufRead`]: trait.BufRead.html
144 #[stable(feature = "rust1", since = "1.0.0")]
145 pub struct Stdin {
146     inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
147 }
148
149 /// A locked reference to the `Stdin` handle.
150 ///
151 /// This handle implements both the [`Read`] and [`BufRead`] traits, and
152 /// is constructed via the [`Stdin::lock`] method.
153 ///
154 /// [`Read`]: trait.Read.html
155 /// [`BufRead`]: trait.BufRead.html
156 /// [`Stdin::lock`]: struct.Stdin.html#method.lock
157 #[stable(feature = "rust1", since = "1.0.0")]
158 pub struct StdinLock<'a> {
159     inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
160 }
161
162 /// Constructs a new handle to the standard input of the current process.
163 ///
164 /// Each handle returned is a reference to a shared global buffer whose access
165 /// is synchronized via a mutex. If you need more explicit control over
166 /// locking, see the [`lock() method`][lock].
167 ///
168 /// [lock]: struct.Stdin.html#method.lock
169 ///
170 /// # Examples
171 ///
172 /// Using implicit synchronization:
173 ///
174 /// ```no_run
175 /// use std::io::{self, Read};
176 ///
177 /// fn main() -> io::Result<()> {
178 ///     let mut buffer = String::new();
179 ///     io::stdin().read_to_string(&mut buffer)?;
180 ///     Ok(())
181 /// }
182 /// ```
183 ///
184 /// Using explicit synchronization:
185 ///
186 /// ```no_run
187 /// use std::io::{self, Read};
188 ///
189 /// fn main() -> io::Result<()> {
190 ///     let mut buffer = String::new();
191 ///     let stdin = io::stdin();
192 ///     let mut handle = stdin.lock();
193 ///
194 ///     handle.read_to_string(&mut buffer)?;
195 ///     Ok(())
196 /// }
197 /// ```
198 #[stable(feature = "rust1", since = "1.0.0")]
199 pub fn stdin() -> Stdin {
200     static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new(stdin_init);
201     return Stdin {
202         inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
203     };
204
205     fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
206         let stdin = match stdin_raw() {
207             Ok(stdin) => Maybe::Real(stdin),
208             _ => Maybe::Fake
209         };
210
211         Arc::new(Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin)))
212     }
213 }
214
215 impl Stdin {
216     /// Locks this handle to the standard input stream, returning a readable
217     /// guard.
218     ///
219     /// The lock is released when the returned lock goes out of scope. The
220     /// returned guard also implements the [`Read`] and [`BufRead`] traits for
221     /// accessing the underlying data.
222     ///
223     /// [`Read`]: trait.Read.html
224     /// [`BufRead`]: trait.BufRead.html
225     ///
226     /// # Examples
227     ///
228     /// ```no_run
229     /// use std::io::{self, Read};
230     ///
231     /// fn main() -> io::Result<()> {
232     ///     let mut buffer = String::new();
233     ///     let stdin = io::stdin();
234     ///     let mut handle = stdin.lock();
235     ///
236     ///     handle.read_to_string(&mut buffer)?;
237     ///     Ok(())
238     /// }
239     /// ```
240     #[stable(feature = "rust1", since = "1.0.0")]
241     pub fn lock(&self) -> StdinLock {
242         StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
243     }
244
245     /// Locks this handle and reads a line of input into the specified buffer.
246     ///
247     /// For detailed semantics of this method, see the documentation on
248     /// [`BufRead::read_line`].
249     ///
250     /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line
251     ///
252     /// # Examples
253     ///
254     /// ```no_run
255     /// use std::io;
256     ///
257     /// let mut input = String::new();
258     /// match io::stdin().read_line(&mut input) {
259     ///     Ok(n) => {
260     ///         println!("{} bytes read", n);
261     ///         println!("{}", input);
262     ///     }
263     ///     Err(error) => println!("error: {}", error),
264     /// }
265     /// ```
266     ///
267     /// You can run the example one of two ways:
268     ///
269     /// - Pipe some text to it, e.g. `printf foo | path/to/executable`
270     /// - Give it text interactively by running the executable directly,
271     ///   in which case it will wait for the Enter key to be pressed before
272     ///   continuing
273     #[stable(feature = "rust1", since = "1.0.0")]
274     pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
275         self.lock().read_line(buf)
276     }
277 }
278
279 #[stable(feature = "std_debug", since = "1.16.0")]
280 impl fmt::Debug for Stdin {
281     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
282         f.pad("Stdin { .. }")
283     }
284 }
285
286 #[stable(feature = "rust1", since = "1.0.0")]
287 impl Read for Stdin {
288     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
289         self.lock().read(buf)
290     }
291     #[inline]
292     unsafe fn initializer(&self) -> Initializer {
293         Initializer::nop()
294     }
295     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
296         self.lock().read_to_end(buf)
297     }
298     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
299         self.lock().read_to_string(buf)
300     }
301     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
302         self.lock().read_exact(buf)
303     }
304 }
305
306 #[stable(feature = "rust1", since = "1.0.0")]
307 impl<'a> Read for StdinLock<'a> {
308     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
309         self.inner.read(buf)
310     }
311     #[inline]
312     unsafe fn initializer(&self) -> Initializer {
313         Initializer::nop()
314     }
315 }
316
317 #[stable(feature = "rust1", since = "1.0.0")]
318 impl<'a> BufRead for StdinLock<'a> {
319     fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
320     fn consume(&mut self, n: usize) { self.inner.consume(n) }
321 }
322
323 #[stable(feature = "std_debug", since = "1.16.0")]
324 impl<'a> fmt::Debug for StdinLock<'a> {
325     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
326         f.pad("StdinLock { .. }")
327     }
328 }
329
330 /// A handle to the global standard output stream of the current process.
331 ///
332 /// Each handle shares a global buffer of data to be written to the standard
333 /// output stream. Access is also synchronized via a lock and explicit control
334 /// over locking is available via the [`lock`] method.
335 ///
336 /// Created by the [`io::stdout`] method.
337 ///
338 /// [`lock`]: #method.lock
339 /// [`io::stdout`]: fn.stdout.html
340 #[stable(feature = "rust1", since = "1.0.0")]
341 pub struct Stdout {
342     // FIXME: this should be LineWriter or BufWriter depending on the state of
343     //        stdout (tty or not). Note that if this is not line buffered it
344     //        should also flush-on-panic or some form of flush-on-abort.
345     inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>,
346 }
347
348 /// A locked reference to the `Stdout` handle.
349 ///
350 /// This handle implements the [`Write`] trait, and is constructed via
351 /// the [`Stdout::lock`] method.
352 ///
353 /// [`Write`]: trait.Write.html
354 /// [`Stdout::lock`]: struct.Stdout.html#method.lock
355 #[stable(feature = "rust1", since = "1.0.0")]
356 pub struct StdoutLock<'a> {
357     inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
358 }
359
360 /// Constructs a new handle to the standard output of the current process.
361 ///
362 /// Each handle returned is a reference to a shared global buffer whose access
363 /// is synchronized via a mutex. If you need more explicit control over
364 /// locking, see the [Stdout::lock] method.
365 ///
366 /// [Stdout::lock]: struct.Stdout.html#method.lock
367 ///
368 /// # Examples
369 ///
370 /// Using implicit synchronization:
371 ///
372 /// ```no_run
373 /// use std::io::{self, Write};
374 ///
375 /// fn main() -> io::Result<()> {
376 ///     io::stdout().write(b"hello world")?;
377 ///
378 ///     Ok(())
379 /// }
380 /// ```
381 ///
382 /// Using explicit synchronization:
383 ///
384 /// ```no_run
385 /// use std::io::{self, Write};
386 ///
387 /// fn main() -> io::Result<()> {
388 ///     let stdout = io::stdout();
389 ///     let mut handle = stdout.lock();
390 ///
391 ///     handle.write(b"hello world")?;
392 ///
393 ///     Ok(())
394 /// }
395 /// ```
396 #[stable(feature = "rust1", since = "1.0.0")]
397 pub fn stdout() -> Stdout {
398     static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>
399         = Lazy::new(stdout_init);
400     return Stdout {
401         inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
402     };
403
404     fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
405         let stdout = match stdout_raw() {
406             Ok(stdout) => Maybe::Real(stdout),
407             _ => Maybe::Fake,
408         };
409         Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))))
410     }
411 }
412
413 impl Stdout {
414     /// Locks this handle to the standard output stream, returning a writable
415     /// guard.
416     ///
417     /// The lock is released when the returned lock goes out of scope. The
418     /// returned guard also implements the `Write` trait for writing data.
419     ///
420     /// # Examples
421     ///
422     /// ```no_run
423     /// use std::io::{self, Write};
424     ///
425     /// fn main() -> io::Result<()> {
426     ///     let stdout = io::stdout();
427     ///     let mut handle = stdout.lock();
428     ///
429     ///     handle.write(b"hello world")?;
430     ///
431     ///     Ok(())
432     /// }
433     /// ```
434     #[stable(feature = "rust1", since = "1.0.0")]
435     pub fn lock(&self) -> StdoutLock {
436         StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
437     }
438 }
439
440 #[stable(feature = "std_debug", since = "1.16.0")]
441 impl fmt::Debug for Stdout {
442     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
443         f.pad("Stdout { .. }")
444     }
445 }
446
447 #[stable(feature = "rust1", since = "1.0.0")]
448 impl Write for Stdout {
449     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
450         self.lock().write(buf)
451     }
452     fn flush(&mut self) -> io::Result<()> {
453         self.lock().flush()
454     }
455     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
456         self.lock().write_all(buf)
457     }
458     fn write_fmt(&mut self, args: fmt::Arguments) -> io::Result<()> {
459         self.lock().write_fmt(args)
460     }
461 }
462 #[stable(feature = "rust1", since = "1.0.0")]
463 impl<'a> Write for StdoutLock<'a> {
464     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
465         self.inner.borrow_mut().write(buf)
466     }
467     fn flush(&mut self) -> io::Result<()> {
468         self.inner.borrow_mut().flush()
469     }
470 }
471
472 #[stable(feature = "std_debug", since = "1.16.0")]
473 impl<'a> fmt::Debug for StdoutLock<'a> {
474     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
475         f.pad("StdoutLock { .. }")
476     }
477 }
478
479 /// A handle to the standard error stream of a process.
480 ///
481 /// For more information, see the [`io::stderr`] method.
482 ///
483 /// [`io::stderr`]: fn.stderr.html
484 #[stable(feature = "rust1", since = "1.0.0")]
485 pub struct Stderr {
486     inner: Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>>,
487 }
488
489 /// A locked reference to the `Stderr` handle.
490 ///
491 /// This handle implements the `Write` trait and is constructed via
492 /// the [`Stderr::lock`] method.
493 ///
494 /// [`Stderr::lock`]: struct.Stderr.html#method.lock
495 #[stable(feature = "rust1", since = "1.0.0")]
496 pub struct StderrLock<'a> {
497     inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
498 }
499
500 /// Constructs a new handle to the standard error of the current process.
501 ///
502 /// This handle is not buffered.
503 ///
504 /// # Examples
505 ///
506 /// Using implicit synchronization:
507 ///
508 /// ```no_run
509 /// use std::io::{self, Write};
510 ///
511 /// fn main() -> io::Result<()> {
512 ///     io::stderr().write(b"hello world")?;
513 ///
514 ///     Ok(())
515 /// }
516 /// ```
517 ///
518 /// Using explicit synchronization:
519 ///
520 /// ```no_run
521 /// use std::io::{self, Write};
522 ///
523 /// fn main() -> io::Result<()> {
524 ///     let stderr = io::stderr();
525 ///     let mut handle = stderr.lock();
526 ///
527 ///     handle.write(b"hello world")?;
528 ///
529 ///     Ok(())
530 /// }
531 /// ```
532 #[stable(feature = "rust1", since = "1.0.0")]
533 pub fn stderr() -> Stderr {
534     static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new(stderr_init);
535     return Stderr {
536         inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
537     };
538
539     fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
540         let stderr = match stderr_raw() {
541             Ok(stderr) => Maybe::Real(stderr),
542             _ => Maybe::Fake,
543         };
544         Arc::new(ReentrantMutex::new(RefCell::new(stderr)))
545     }
546 }
547
548 impl Stderr {
549     /// Locks this handle to the standard error stream, returning a writable
550     /// guard.
551     ///
552     /// The lock is released when the returned lock goes out of scope. The
553     /// returned guard also implements the `Write` trait for writing data.
554     ///
555     /// # Examples
556     ///
557     /// ```
558     /// use std::io::{self, Write};
559     ///
560     /// fn foo() -> io::Result<()> {
561     ///     let stderr = io::stderr();
562     ///     let mut handle = stderr.lock();
563     ///
564     ///     handle.write(b"hello world")?;
565     ///
566     ///     Ok(())
567     /// }
568     /// ```
569     #[stable(feature = "rust1", since = "1.0.0")]
570     pub fn lock(&self) -> StderrLock {
571         StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
572     }
573 }
574
575 #[stable(feature = "std_debug", since = "1.16.0")]
576 impl fmt::Debug for Stderr {
577     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
578         f.pad("Stderr { .. }")
579     }
580 }
581
582 #[stable(feature = "rust1", since = "1.0.0")]
583 impl Write for Stderr {
584     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
585         self.lock().write(buf)
586     }
587     fn flush(&mut self) -> io::Result<()> {
588         self.lock().flush()
589     }
590     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
591         self.lock().write_all(buf)
592     }
593     fn write_fmt(&mut self, args: fmt::Arguments) -> io::Result<()> {
594         self.lock().write_fmt(args)
595     }
596 }
597 #[stable(feature = "rust1", since = "1.0.0")]
598 impl<'a> Write for StderrLock<'a> {
599     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
600         self.inner.borrow_mut().write(buf)
601     }
602     fn flush(&mut self) -> io::Result<()> {
603         self.inner.borrow_mut().flush()
604     }
605 }
606
607 #[stable(feature = "std_debug", since = "1.16.0")]
608 impl<'a> fmt::Debug for StderrLock<'a> {
609     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
610         f.pad("StderrLock { .. }")
611     }
612 }
613
614 /// Resets the thread-local stderr handle to the specified writer
615 ///
616 /// This will replace the current thread's stderr handle, returning the old
617 /// handle. All future calls to `panic!` and friends will emit their output to
618 /// this specified handle.
619 ///
620 /// Note that this does not need to be called for all new threads; the default
621 /// output handle is to the process's stderr stream.
622 #[unstable(feature = "set_stdio",
623            reason = "this function may disappear completely or be replaced \
624                      with a more general mechanism",
625            issue = "0")]
626 #[doc(hidden)]
627 pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
628     use panicking::LOCAL_STDERR;
629     use mem;
630     LOCAL_STDERR.with(move |slot| {
631         mem::replace(&mut *slot.borrow_mut(), sink)
632     }).and_then(|mut s| {
633         let _ = s.flush();
634         Some(s)
635     })
636 }
637
638 /// Resets the thread-local stdout handle to the specified writer
639 ///
640 /// This will replace the current thread's stdout handle, returning the old
641 /// handle. All future calls to `print!` and friends will emit their output to
642 /// this specified handle.
643 ///
644 /// Note that this does not need to be called for all new threads; the default
645 /// output handle is to the process's stdout stream.
646 #[unstable(feature = "set_stdio",
647            reason = "this function may disappear completely or be replaced \
648                      with a more general mechanism",
649            issue = "0")]
650 #[doc(hidden)]
651 pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
652     use mem;
653     LOCAL_STDOUT.with(move |slot| {
654         mem::replace(&mut *slot.borrow_mut(), sink)
655     }).and_then(|mut s| {
656         let _ = s.flush();
657         Some(s)
658     })
659 }
660
661 /// Write `args` to output stream `local_s` if possible, `global_s`
662 /// otherwise. `label` identifies the stream in a panic message.
663 ///
664 /// This function is used to print error messages, so it takes extra
665 /// care to avoid causing a panic when `local_stream` is unusable.
666 /// For instance, if the TLS key for the local stream is
667 /// already destroyed, or if the local stream is locked by another
668 /// thread, it will just fall back to the global stream.
669 ///
670 /// However, if the actual I/O causes an error, this function does panic.
671 fn print_to<T>(
672     args: fmt::Arguments,
673     local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
674     global_s: fn() -> T,
675     label: &str,
676 )
677 where
678     T: Write,
679 {
680     let result = local_s.try_with(|s| {
681         if let Ok(mut borrowed) = s.try_borrow_mut() {
682             if let Some(w) = borrowed.as_mut() {
683                 return w.write_fmt(args);
684             }
685         }
686         global_s().write_fmt(args)
687     }).unwrap_or_else(|_| {
688         global_s().write_fmt(args)
689     });
690
691     if let Err(e) = result {
692         panic!("failed printing to {}: {}", label, e);
693     }
694 }
695
696 #[unstable(feature = "print_internals",
697            reason = "implementation detail which may disappear or be replaced at any time",
698            issue = "0")]
699 #[doc(hidden)]
700 pub fn _print(args: fmt::Arguments) {
701     print_to(args, &LOCAL_STDOUT, stdout, "stdout");
702 }
703
704 #[unstable(feature = "print_internals",
705            reason = "implementation detail which may disappear or be replaced at any time",
706            issue = "0")]
707 #[doc(hidden)]
708 pub fn _eprint(args: fmt::Arguments) {
709     use panicking::LOCAL_STDERR;
710     print_to(args, &LOCAL_STDERR, stderr, "stderr");
711 }
712
713 #[cfg(test)]
714 mod tests {
715     use panic::{UnwindSafe, RefUnwindSafe};
716     use thread;
717     use super::*;
718
719     #[test]
720     fn stdout_unwind_safe() {
721         assert_unwind_safe::<Stdout>();
722     }
723     #[test]
724     fn stdoutlock_unwind_safe() {
725         assert_unwind_safe::<StdoutLock>();
726         assert_unwind_safe::<StdoutLock<'static>>();
727     }
728     #[test]
729     fn stderr_unwind_safe() {
730         assert_unwind_safe::<Stderr>();
731     }
732     #[test]
733     fn stderrlock_unwind_safe() {
734         assert_unwind_safe::<StderrLock>();
735         assert_unwind_safe::<StderrLock<'static>>();
736     }
737
738     fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}
739
740     #[test]
741     #[cfg_attr(target_os = "emscripten", ignore)]
742     fn panic_doesnt_poison() {
743         thread::spawn(|| {
744             let _a = stdin();
745             let _a = _a.lock();
746             let _a = stdout();
747             let _a = _a.lock();
748             let _a = stderr();
749             let _a = _a.lock();
750             panic!();
751         }).join().unwrap_err();
752
753         let _a = stdin();
754         let _a = _a.lock();
755         let _a = stdout();
756         let _a = _a.lock();
757         let _a = stderr();
758         let _a = _a.lock();
759     }
760 }