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