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