1 #![cfg_attr(test, allow(unused))]
6 use crate::io::prelude::*;
8 use crate::cell::{Cell, RefCell};
11 use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
12 use crate::sync::atomic::{AtomicBool, Ordering};
13 use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard};
14 use crate::sys::stdio;
16 type LocalStream = Arc<Mutex<Vec<u8>>>;
19 /// Used by the test crate to capture the output of the print macros and panics.
20 static OUTPUT_CAPTURE: Cell<Option<LocalStream>> = {
25 /// Flag to indicate OUTPUT_CAPTURE is used.
27 /// If it is None and was never set on any thread, this flag is set to false,
28 /// and OUTPUT_CAPTURE can be safely ignored on all threads, saving some time
29 /// and memory registering an unused thread local.
31 /// Note about memory ordering: This contains information about whether a
32 /// thread local variable might be in use. Although this is a global flag, the
33 /// memory ordering between threads does not matter: we only want this flag to
34 /// have a consistent order between set_output_capture and print_to *within
35 /// the same thread*. Within the same thread, things always have a perfectly
36 /// consistent order. So Ordering::Relaxed is fine.
37 static OUTPUT_CAPTURE_USED: AtomicBool = AtomicBool::new(false);
39 /// A handle to a raw instance of the standard input stream of this process.
41 /// This handle is not synchronized or buffered in any fashion. Constructed via
42 /// the `std::io::stdio::stdin_raw` function.
43 struct StdinRaw(stdio::Stdin);
45 /// A handle to a raw instance of the standard output stream of this process.
47 /// This handle is not synchronized or buffered in any fashion. Constructed via
48 /// the `std::io::stdio::stdout_raw` function.
49 struct StdoutRaw(stdio::Stdout);
51 /// A handle to a raw instance of the standard output stream of this process.
53 /// This handle is not synchronized or buffered in any fashion. Constructed via
54 /// the `std::io::stdio::stderr_raw` function.
55 struct StderrRaw(stdio::Stderr);
57 /// Constructs a new raw handle to the standard input of this process.
59 /// The returned handle does not interact with any other handles created nor
60 /// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
61 /// handles is **not** available to raw handles returned from this function.
63 /// The returned handle has no external synchronization or buffering.
64 #[unstable(feature = "libstd_sys_internals", issue = "none")]
65 const fn stdin_raw() -> StdinRaw {
66 StdinRaw(stdio::Stdin::new())
69 /// Constructs a new raw handle to the standard output stream of this process.
71 /// The returned handle does not interact with any other handles created nor
72 /// handles returned by `std::io::stdout`. Note that data is buffered by the
73 /// `std::io::stdout` handles so writes which happen via this raw handle may
74 /// appear before previous writes.
76 /// The returned handle has no external synchronization or buffering layered on
78 #[unstable(feature = "libstd_sys_internals", issue = "none")]
79 const fn stdout_raw() -> StdoutRaw {
80 StdoutRaw(stdio::Stdout::new())
83 /// Constructs a new raw handle to the standard error stream of this process.
85 /// The returned handle does not interact with any other handles created nor
86 /// handles returned by `std::io::stderr`.
88 /// The returned handle has no external synchronization or buffering layered on
90 #[unstable(feature = "libstd_sys_internals", issue = "none")]
91 const fn stderr_raw() -> StderrRaw {
92 StderrRaw(stdio::Stderr::new())
95 impl Read for StdinRaw {
96 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
97 handle_ebadf(self.0.read(buf), 0)
100 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
101 handle_ebadf(self.0.read_vectored(bufs), 0)
105 fn is_read_vectored(&self) -> bool {
106 self.0.is_read_vectored()
109 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
110 handle_ebadf(self.0.read_to_end(buf), 0)
113 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
114 handle_ebadf(self.0.read_to_string(buf), 0)
118 impl Write for StdoutRaw {
119 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
120 handle_ebadf(self.0.write(buf), buf.len())
123 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
124 let total = bufs.iter().map(|b| b.len()).sum();
125 handle_ebadf(self.0.write_vectored(bufs), total)
129 fn is_write_vectored(&self) -> bool {
130 self.0.is_write_vectored()
133 fn flush(&mut self) -> io::Result<()> {
134 handle_ebadf(self.0.flush(), ())
137 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
138 handle_ebadf(self.0.write_all(buf), ())
141 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
142 handle_ebadf(self.0.write_all_vectored(bufs), ())
145 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
146 handle_ebadf(self.0.write_fmt(fmt), ())
150 impl Write for StderrRaw {
151 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
152 handle_ebadf(self.0.write(buf), buf.len())
155 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
156 let total = bufs.iter().map(|b| b.len()).sum();
157 handle_ebadf(self.0.write_vectored(bufs), total)
161 fn is_write_vectored(&self) -> bool {
162 self.0.is_write_vectored()
165 fn flush(&mut self) -> io::Result<()> {
166 handle_ebadf(self.0.flush(), ())
169 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
170 handle_ebadf(self.0.write_all(buf), ())
173 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
174 handle_ebadf(self.0.write_all_vectored(bufs), ())
177 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
178 handle_ebadf(self.0.write_fmt(fmt), ())
182 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
184 Err(ref e) if stdio::is_ebadf(e) => Ok(default),
189 /// A handle to the standard input stream of a process.
191 /// Each handle is a shared reference to a global buffer of input data to this
192 /// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
193 /// (e.g., `.lines()`). Reads to this handle are otherwise locked with respect
196 /// This handle implements the `Read` trait, but beware that concurrent reads
197 /// of `Stdin` must be executed with care.
199 /// Created by the [`io::stdin`] method.
201 /// [`io::stdin`]: stdin
203 /// ### Note: Windows Portability Considerations
205 /// When operating in a console, the Windows implementation of this stream does not support
206 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
209 /// In a process with a detached console, such as one using
210 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
211 /// the contained handle will be null. In such cases, the standard library's `Read` and
212 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
213 /// standard library or via raw Windows API calls, will fail.
220 /// fn main() -> io::Result<()> {
221 /// let mut buffer = String::new();
222 /// let stdin = io::stdin(); // We get `Stdin` here.
223 /// stdin.read_line(&mut buffer)?;
227 #[stable(feature = "rust1", since = "1.0.0")]
229 inner: &'static Mutex<BufReader<StdinRaw>>,
232 /// A locked reference to the [`Stdin`] handle.
234 /// This handle implements both the [`Read`] and [`BufRead`] traits, and
235 /// is constructed via the [`Stdin::lock`] method.
237 /// ### Note: Windows Portability Considerations
239 /// When operating in a console, the Windows implementation of this stream does not support
240 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
243 /// In a process with a detached console, such as one using
244 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
245 /// the contained handle will be null. In such cases, the standard library's `Read` and
246 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
247 /// standard library or via raw Windows API calls, will fail.
252 /// use std::io::{self, BufRead};
254 /// fn main() -> io::Result<()> {
255 /// let mut buffer = String::new();
256 /// let stdin = io::stdin(); // We get `Stdin` here.
258 /// let mut handle = stdin.lock(); // We get `StdinLock` here.
259 /// handle.read_line(&mut buffer)?;
260 /// } // `StdinLock` is dropped here.
264 #[must_use = "if unused stdin will immediately unlock"]
265 #[stable(feature = "rust1", since = "1.0.0")]
266 pub struct StdinLock<'a> {
267 inner: MutexGuard<'a, BufReader<StdinRaw>>,
270 /// Constructs a new handle to the standard input of the current process.
272 /// Each handle returned is a reference to a shared global buffer whose access
273 /// is synchronized via a mutex. If you need more explicit control over
274 /// locking, see the [`Stdin::lock`] method.
276 /// ### Note: Windows Portability Considerations
278 /// When operating in a console, the Windows implementation of this stream does not support
279 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
282 /// In a process with a detached console, such as one using
283 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
284 /// the contained handle will be null. In such cases, the standard library's `Read` and
285 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
286 /// standard library or via raw Windows API calls, will fail.
290 /// Using implicit synchronization:
295 /// fn main() -> io::Result<()> {
296 /// let mut buffer = String::new();
297 /// io::stdin().read_line(&mut buffer)?;
302 /// Using explicit synchronization:
305 /// use std::io::{self, BufRead};
307 /// fn main() -> io::Result<()> {
308 /// let mut buffer = String::new();
309 /// let stdin = io::stdin();
310 /// let mut handle = stdin.lock();
312 /// handle.read_line(&mut buffer)?;
317 #[stable(feature = "rust1", since = "1.0.0")]
318 pub fn stdin() -> Stdin {
319 static INSTANCE: OnceLock<Mutex<BufReader<StdinRaw>>> = OnceLock::new();
321 inner: INSTANCE.get_or_init(|| {
322 Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin_raw()))
328 /// Locks this handle to the standard input stream, returning a readable
331 /// The lock is released when the returned lock goes out of scope. The
332 /// returned guard also implements the [`Read`] and [`BufRead`] traits for
333 /// accessing the underlying data.
338 /// use std::io::{self, BufRead};
340 /// fn main() -> io::Result<()> {
341 /// let mut buffer = String::new();
342 /// let stdin = io::stdin();
343 /// let mut handle = stdin.lock();
345 /// handle.read_line(&mut buffer)?;
349 #[stable(feature = "rust1", since = "1.0.0")]
350 pub fn lock(&self) -> StdinLock<'static> {
351 // Locks this handle with 'static lifetime. This depends on the
352 // implementation detail that the underlying `Mutex` is static.
353 StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
356 /// Locks this handle and reads a line of input, appending it to the specified buffer.
358 /// For detailed semantics of this method, see the documentation on
359 /// [`BufRead::read_line`].
366 /// let mut input = String::new();
367 /// match io::stdin().read_line(&mut input) {
369 /// println!("{n} bytes read");
370 /// println!("{input}");
372 /// Err(error) => println!("error: {error}"),
376 /// You can run the example one of two ways:
378 /// - Pipe some text to it, e.g., `printf foo | path/to/executable`
379 /// - Give it text interactively by running the executable directly,
380 /// in which case it will wait for the Enter key to be pressed before
382 #[stable(feature = "rust1", since = "1.0.0")]
383 pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
384 self.lock().read_line(buf)
387 /// Consumes this handle and returns an iterator over input lines.
389 /// For detailed semantics of this method, see the documentation on
390 /// [`BufRead::lines`].
397 /// let lines = io::stdin().lines();
398 /// for line in lines {
399 /// println!("got a line: {}", line.unwrap());
402 #[must_use = "`self` will be dropped if the result is not used"]
403 #[stable(feature = "stdin_forwarders", since = "1.62.0")]
404 pub fn lines(self) -> Lines<StdinLock<'static>> {
409 #[stable(feature = "std_debug", since = "1.16.0")]
410 impl fmt::Debug for Stdin {
411 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
412 f.debug_struct("Stdin").finish_non_exhaustive()
416 #[stable(feature = "rust1", since = "1.0.0")]
417 impl Read for Stdin {
418 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
419 self.lock().read(buf)
421 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
422 self.lock().read_vectored(bufs)
425 fn is_read_vectored(&self) -> bool {
426 self.lock().is_read_vectored()
428 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
429 self.lock().read_to_end(buf)
431 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
432 self.lock().read_to_string(buf)
434 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
435 self.lock().read_exact(buf)
439 // only used by platform-dependent io::copy specializations, i.e. unused on some platforms
440 #[cfg(any(target_os = "linux", target_os = "android"))]
442 pub(crate) fn as_mut_buf(&mut self) -> &mut BufReader<impl Read> {
447 #[stable(feature = "rust1", since = "1.0.0")]
448 impl Read for StdinLock<'_> {
449 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
453 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
454 self.inner.read_vectored(bufs)
458 fn is_read_vectored(&self) -> bool {
459 self.inner.is_read_vectored()
462 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
463 self.inner.read_to_end(buf)
466 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
467 self.inner.read_to_string(buf)
470 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
471 self.inner.read_exact(buf)
475 #[stable(feature = "rust1", since = "1.0.0")]
476 impl BufRead for StdinLock<'_> {
477 fn fill_buf(&mut self) -> io::Result<&[u8]> {
478 self.inner.fill_buf()
481 fn consume(&mut self, n: usize) {
482 self.inner.consume(n)
485 fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
486 self.inner.read_until(byte, buf)
489 fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
490 self.inner.read_line(buf)
494 #[stable(feature = "std_debug", since = "1.16.0")]
495 impl fmt::Debug for StdinLock<'_> {
496 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
497 f.debug_struct("StdinLock").finish_non_exhaustive()
501 /// A handle to the global standard output stream of the current process.
503 /// Each handle shares a global buffer of data to be written to the standard
504 /// output stream. Access is also synchronized via a lock and explicit control
505 /// over locking is available via the [`lock`] method.
507 /// Created by the [`io::stdout`] method.
509 /// ### Note: Windows Portability Considerations
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
515 /// In a process with a detached console, such as one using
516 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
517 /// the contained handle will be null. In such cases, the standard library's `Read` and
518 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
519 /// standard library or via raw Windows API calls, will fail.
521 /// [`lock`]: Stdout::lock
522 /// [`io::stdout`]: stdout
523 #[stable(feature = "rust1", since = "1.0.0")]
525 // FIXME: this should be LineWriter or BufWriter depending on the state of
526 // stdout (tty or not). Note that if this is not line buffered it
527 // should also flush-on-panic or some form of flush-on-abort.
528 inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
531 /// A locked reference to the [`Stdout`] handle.
533 /// This handle implements the [`Write`] trait, and is constructed via
534 /// the [`Stdout::lock`] method. See its documentation for more.
536 /// ### Note: Windows Portability Considerations
538 /// When operating in a console, the Windows implementation of this stream does not support
539 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
542 /// In a process with a detached console, such as one using
543 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
544 /// the contained handle will be null. In such cases, the standard library's `Read` and
545 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
546 /// standard library or via raw Windows API calls, will fail.
547 #[must_use = "if unused stdout will immediately unlock"]
548 #[stable(feature = "rust1", since = "1.0.0")]
549 pub struct StdoutLock<'a> {
550 inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
553 static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
555 /// Constructs a new handle to the standard output of the current process.
557 /// Each handle returned is a reference to a shared global buffer whose access
558 /// is synchronized via a mutex. If you need more explicit control over
559 /// locking, see the [`Stdout::lock`] method.
561 /// ### Note: Windows Portability Considerations
563 /// When operating in a console, the Windows implementation of this stream does not support
564 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
567 /// In a process with a detached console, such as one using
568 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
569 /// the contained handle will be null. In such cases, the standard library's `Read` and
570 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
571 /// standard library or via raw Windows API calls, will fail.
575 /// Using implicit synchronization:
578 /// use std::io::{self, Write};
580 /// fn main() -> io::Result<()> {
581 /// io::stdout().write_all(b"hello world")?;
587 /// Using explicit synchronization:
590 /// use std::io::{self, Write};
592 /// fn main() -> io::Result<()> {
593 /// let stdout = io::stdout();
594 /// let mut handle = stdout.lock();
596 /// handle.write_all(b"hello world")?;
602 #[stable(feature = "rust1", since = "1.0.0")]
603 pub fn stdout() -> Stdout {
606 .get_or_init(|| ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))),
610 // Flush the data and disable buffering during shutdown
611 // by replacing the line writer by one with zero
612 // buffering capacity.
614 let mut initialized = false;
615 let stdout = STDOUT.get_or_init(|| {
617 ReentrantMutex::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
621 // The buffer was previously initialized, overwrite it here.
622 // We use try_lock() instead of lock(), because someone
623 // might have leaked a StdoutLock, which would
624 // otherwise cause a deadlock here.
625 if let Some(lock) = stdout.try_lock() {
626 *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
632 /// Locks this handle to the standard output stream, returning a writable
635 /// The lock is released when the returned lock goes out of scope. The
636 /// returned guard also implements the `Write` trait for writing data.
641 /// use std::io::{self, Write};
643 /// fn main() -> io::Result<()> {
644 /// let mut stdout = io::stdout().lock();
646 /// stdout.write_all(b"hello world")?;
651 #[stable(feature = "rust1", since = "1.0.0")]
652 pub fn lock(&self) -> StdoutLock<'static> {
653 // Locks this handle with 'static lifetime. This depends on the
654 // implementation detail that the underlying `ReentrantMutex` is
656 StdoutLock { inner: self.inner.lock() }
660 #[stable(feature = "std_debug", since = "1.16.0")]
661 impl fmt::Debug for Stdout {
662 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
663 f.debug_struct("Stdout").finish_non_exhaustive()
667 #[stable(feature = "rust1", since = "1.0.0")]
668 impl Write for Stdout {
669 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
672 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
673 (&*self).write_vectored(bufs)
676 fn is_write_vectored(&self) -> bool {
677 io::Write::is_write_vectored(&&*self)
679 fn flush(&mut self) -> io::Result<()> {
682 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
683 (&*self).write_all(buf)
685 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
686 (&*self).write_all_vectored(bufs)
688 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
689 (&*self).write_fmt(args)
693 #[stable(feature = "write_mt", since = "1.48.0")]
694 impl Write for &Stdout {
695 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
696 self.lock().write(buf)
698 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
699 self.lock().write_vectored(bufs)
702 fn is_write_vectored(&self) -> bool {
703 self.lock().is_write_vectored()
705 fn flush(&mut self) -> io::Result<()> {
708 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
709 self.lock().write_all(buf)
711 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
712 self.lock().write_all_vectored(bufs)
714 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
715 self.lock().write_fmt(args)
719 #[stable(feature = "rust1", since = "1.0.0")]
720 impl Write for StdoutLock<'_> {
721 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
722 self.inner.borrow_mut().write(buf)
724 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
725 self.inner.borrow_mut().write_vectored(bufs)
728 fn is_write_vectored(&self) -> bool {
729 self.inner.borrow_mut().is_write_vectored()
731 fn flush(&mut self) -> io::Result<()> {
732 self.inner.borrow_mut().flush()
734 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
735 self.inner.borrow_mut().write_all(buf)
737 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
738 self.inner.borrow_mut().write_all_vectored(bufs)
742 #[stable(feature = "std_debug", since = "1.16.0")]
743 impl fmt::Debug for StdoutLock<'_> {
744 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
745 f.debug_struct("StdoutLock").finish_non_exhaustive()
749 /// A handle to the standard error stream of a process.
751 /// For more information, see the [`io::stderr`] method.
753 /// [`io::stderr`]: stderr
755 /// ### Note: Windows Portability Considerations
757 /// When operating in a console, the Windows implementation of this stream does not support
758 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
761 /// In a process with a detached console, such as one using
762 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
763 /// the contained handle will be null. In such cases, the standard library's `Read` and
764 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
765 /// standard library or via raw Windows API calls, will fail.
766 #[stable(feature = "rust1", since = "1.0.0")]
768 inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
771 /// A locked reference to the [`Stderr`] handle.
773 /// This handle implements the [`Write`] trait and is constructed via
774 /// the [`Stderr::lock`] method. See its documentation for more.
776 /// ### Note: Windows Portability Considerations
778 /// When operating in a console, the Windows implementation of this stream does not support
779 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
782 /// In a process with a detached console, such as one using
783 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
784 /// the contained handle will be null. In such cases, the standard library's `Read` and
785 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
786 /// standard library or via raw Windows API calls, will fail.
787 #[must_use = "if unused stderr will immediately unlock"]
788 #[stable(feature = "rust1", since = "1.0.0")]
789 pub struct StderrLock<'a> {
790 inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
793 /// Constructs a new handle to the standard error of the current process.
795 /// This handle is not buffered.
797 /// ### Note: Windows Portability Considerations
799 /// When operating in a console, the Windows implementation of this stream does not support
800 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
803 /// In a process with a detached console, such as one using
804 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
805 /// the contained handle will be null. In such cases, the standard library's `Read` and
806 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
807 /// standard library or via raw Windows API calls, will fail.
811 /// Using implicit synchronization:
814 /// use std::io::{self, Write};
816 /// fn main() -> io::Result<()> {
817 /// io::stderr().write_all(b"hello world")?;
823 /// Using explicit synchronization:
826 /// use std::io::{self, Write};
828 /// fn main() -> io::Result<()> {
829 /// let stderr = io::stderr();
830 /// let mut handle = stderr.lock();
832 /// handle.write_all(b"hello world")?;
838 #[stable(feature = "rust1", since = "1.0.0")]
839 pub fn stderr() -> Stderr {
840 // Note that unlike `stdout()` we don't use `at_exit` here to register a
841 // destructor. Stderr is not buffered, so there's no need to run a
842 // destructor for flushing the buffer
843 static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
844 ReentrantMutex::new(RefCell::new(stderr_raw()));
846 Stderr { inner: &INSTANCE }
850 /// Locks this handle to the standard error stream, returning a writable
853 /// The lock is released when the returned lock goes out of scope. The
854 /// returned guard also implements the [`Write`] trait for writing data.
859 /// use std::io::{self, Write};
861 /// fn foo() -> io::Result<()> {
862 /// let stderr = io::stderr();
863 /// let mut handle = stderr.lock();
865 /// handle.write_all(b"hello world")?;
870 #[stable(feature = "rust1", since = "1.0.0")]
871 pub fn lock(&self) -> StderrLock<'static> {
872 // Locks this handle with 'static lifetime. This depends on the
873 // implementation detail that the underlying `ReentrantMutex` is
875 StderrLock { inner: self.inner.lock() }
879 #[stable(feature = "std_debug", since = "1.16.0")]
880 impl fmt::Debug for Stderr {
881 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
882 f.debug_struct("Stderr").finish_non_exhaustive()
886 #[stable(feature = "rust1", since = "1.0.0")]
887 impl Write for Stderr {
888 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
891 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
892 (&*self).write_vectored(bufs)
895 fn is_write_vectored(&self) -> bool {
896 io::Write::is_write_vectored(&&*self)
898 fn flush(&mut self) -> io::Result<()> {
901 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
902 (&*self).write_all(buf)
904 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
905 (&*self).write_all_vectored(bufs)
907 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
908 (&*self).write_fmt(args)
912 #[stable(feature = "write_mt", since = "1.48.0")]
913 impl Write for &Stderr {
914 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
915 self.lock().write(buf)
917 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
918 self.lock().write_vectored(bufs)
921 fn is_write_vectored(&self) -> bool {
922 self.lock().is_write_vectored()
924 fn flush(&mut self) -> io::Result<()> {
927 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
928 self.lock().write_all(buf)
930 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
931 self.lock().write_all_vectored(bufs)
933 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
934 self.lock().write_fmt(args)
938 #[stable(feature = "rust1", since = "1.0.0")]
939 impl Write for StderrLock<'_> {
940 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
941 self.inner.borrow_mut().write(buf)
943 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
944 self.inner.borrow_mut().write_vectored(bufs)
947 fn is_write_vectored(&self) -> bool {
948 self.inner.borrow_mut().is_write_vectored()
950 fn flush(&mut self) -> io::Result<()> {
951 self.inner.borrow_mut().flush()
953 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
954 self.inner.borrow_mut().write_all(buf)
956 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
957 self.inner.borrow_mut().write_all_vectored(bufs)
961 #[stable(feature = "std_debug", since = "1.16.0")]
962 impl fmt::Debug for StderrLock<'_> {
963 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
964 f.debug_struct("StderrLock").finish_non_exhaustive()
968 /// Sets the thread-local output capture buffer and returns the old one.
970 feature = "internal_output_capture",
971 reason = "this function is meant for use in the test crate \
972 and may disappear in the future",
976 pub fn set_output_capture(sink: Option<LocalStream>) -> Option<LocalStream> {
977 if sink.is_none() && !OUTPUT_CAPTURE_USED.load(Ordering::Relaxed) {
978 // OUTPUT_CAPTURE is definitely None since OUTPUT_CAPTURE_USED is false.
981 OUTPUT_CAPTURE_USED.store(true, Ordering::Relaxed);
982 OUTPUT_CAPTURE.with(move |slot| slot.replace(sink))
985 /// Write `args` to the capture buffer if enabled and possible, or `global_s`
986 /// otherwise. `label` identifies the stream in a panic message.
988 /// This function is used to print error messages, so it takes extra
989 /// care to avoid causing a panic when `OUTPUT_CAPTURE` is unusable.
990 /// For instance, if the TLS key for output capturing is already destroyed, or
991 /// if the local stream is in use by another thread, it will just fall back to
992 /// the global stream.
994 /// However, if the actual I/O causes an error, this function does panic.
996 /// Writing to non-blocking stdout/stderr can cause an error, which will lead
997 /// this function to panic.
998 fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str)
1002 if print_to_buffer_if_capture_used(args) {
1003 // Successfully wrote to capture buffer.
1007 if let Err(e) = global_s().write_fmt(args) {
1008 panic!("failed printing to {label}: {e}");
1012 fn print_to_buffer_if_capture_used(args: fmt::Arguments<'_>) -> bool {
1013 OUTPUT_CAPTURE_USED.load(Ordering::Relaxed)
1014 && OUTPUT_CAPTURE.try_with(|s| {
1015 // Note that we completely remove a local sink to write to in case
1016 // our printing recursively panics/prints, so the recursive
1017 // panic/print goes to the global sink instead of our local sink.
1019 let _ = w.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(args);
1025 /// Used by impl Termination for Result to print error after `main` or a test
1026 /// has returned. Should avoid panicking, although we can't help it if one of
1027 /// the Display impls inside args decides to.
1028 pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) {
1029 if print_to_buffer_if_capture_used(args) {
1033 // Ignore error if the write fails, for example because stderr is already
1034 // closed. There is not much point panicking at this point.
1035 let _ = stderr().write_fmt(args);
1038 /// Trait to determine if a descriptor/handle refers to a terminal/tty.
1039 #[unstable(feature = "is_terminal", issue = "98070")]
1040 pub trait IsTerminal: crate::sealed::Sealed {
1041 /// Returns `true` if the descriptor/handle refers to a terminal/tty.
1043 /// On platforms where Rust does not know how to detect a terminal yet, this will return
1044 /// `false`. This will also return `false` if an unexpected error occurred, such as from
1045 /// passing an invalid file descriptor.
1046 fn is_terminal(&self) -> bool;
1049 macro_rules! impl_is_terminal {
1050 ($($t:ty),*$(,)?) => {$(
1051 #[unstable(feature = "sealed", issue = "none")]
1052 impl crate::sealed::Sealed for $t {}
1054 #[unstable(feature = "is_terminal", issue = "98070")]
1055 impl IsTerminal for $t {
1057 fn is_terminal(&self) -> bool {
1058 crate::sys::io::is_terminal(self)
1064 impl_is_terminal!(File, Stdin, StdinLock<'_>, Stdout, StdoutLock<'_>, Stderr, StderrLock<'_>);
1067 feature = "print_internals",
1068 reason = "implementation detail which may disappear or be replaced at any time",
1073 pub fn _print(args: fmt::Arguments<'_>) {
1074 print_to(args, stdout, "stdout");
1078 feature = "print_internals",
1079 reason = "implementation detail which may disappear or be replaced at any time",
1084 pub fn _eprint(args: fmt::Arguments<'_>) {
1085 print_to(args, stderr, "stderr");
1089 pub use realstd::io::{_eprint, _print};