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};
14 use crate::sys::stdio;
15 use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
17 type LocalStream = Arc<Mutex<Vec<u8>>>;
20 /// Used by the test crate to capture the output of the print macros and panics.
21 static OUTPUT_CAPTURE: Cell<Option<LocalStream>> = {
26 /// Flag to indicate OUTPUT_CAPTURE is used.
28 /// If it is None and was never set on any thread, this flag is set to false,
29 /// and OUTPUT_CAPTURE can be safely ignored on all threads, saving some time
30 /// and memory registering an unused thread local.
32 /// Note about memory ordering: This contains information about whether a
33 /// thread local variable might be in use. Although this is a global flag, the
34 /// memory ordering between threads does not matter: we only want this flag to
35 /// have a consistent order between set_output_capture and print_to *within
36 /// the same thread*. Within the same thread, things always have a perfectly
37 /// consistent order. So Ordering::Relaxed is fine.
38 static OUTPUT_CAPTURE_USED: AtomicBool = AtomicBool::new(false);
40 /// A handle to a raw instance of the standard input stream of this process.
42 /// This handle is not synchronized or buffered in any fashion. Constructed via
43 /// the `std::io::stdio::stdin_raw` function.
44 struct StdinRaw(stdio::Stdin);
46 /// A handle to a raw instance of the standard output stream of this process.
48 /// This handle is not synchronized or buffered in any fashion. Constructed via
49 /// the `std::io::stdio::stdout_raw` function.
50 struct StdoutRaw(stdio::Stdout);
52 /// A handle to a raw instance of the standard output stream of this process.
54 /// This handle is not synchronized or buffered in any fashion. Constructed via
55 /// the `std::io::stdio::stderr_raw` function.
56 struct StderrRaw(stdio::Stderr);
58 /// Constructs a new raw handle to the standard input of this process.
60 /// The returned handle does not interact with any other handles created nor
61 /// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
62 /// handles is **not** available to raw handles returned from this function.
64 /// The returned handle has no external synchronization or buffering.
65 #[unstable(feature = "libstd_sys_internals", issue = "none")]
66 const fn stdin_raw() -> StdinRaw {
67 StdinRaw(stdio::Stdin::new())
70 /// Constructs a new raw handle to the standard output stream of this process.
72 /// The returned handle does not interact with any other handles created nor
73 /// handles returned by `std::io::stdout`. Note that data is buffered by the
74 /// `std::io::stdout` handles so writes which happen via this raw handle may
75 /// appear before previous writes.
77 /// The returned handle has no external synchronization or buffering layered on
79 #[unstable(feature = "libstd_sys_internals", issue = "none")]
80 const fn stdout_raw() -> StdoutRaw {
81 StdoutRaw(stdio::Stdout::new())
84 /// Constructs a new raw handle to the standard error stream of this process.
86 /// The returned handle does not interact with any other handles created nor
87 /// handles returned by `std::io::stderr`.
89 /// The returned handle has no external synchronization or buffering layered on
91 #[unstable(feature = "libstd_sys_internals", issue = "none")]
92 const fn stderr_raw() -> StderrRaw {
93 StderrRaw(stdio::Stderr::new())
96 impl Read for StdinRaw {
97 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
98 handle_ebadf(self.0.read(buf), 0)
101 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
102 handle_ebadf(self.0.read_vectored(bufs), 0)
106 fn is_read_vectored(&self) -> bool {
107 self.0.is_read_vectored()
110 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
111 handle_ebadf(self.0.read_to_end(buf), 0)
114 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
115 handle_ebadf(self.0.read_to_string(buf), 0)
119 impl Write for StdoutRaw {
120 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
121 handle_ebadf(self.0.write(buf), buf.len())
124 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
125 let total = bufs.iter().map(|b| b.len()).sum();
126 handle_ebadf(self.0.write_vectored(bufs), total)
130 fn is_write_vectored(&self) -> bool {
131 self.0.is_write_vectored()
134 fn flush(&mut self) -> io::Result<()> {
135 handle_ebadf(self.0.flush(), ())
138 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
139 handle_ebadf(self.0.write_all(buf), ())
142 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
143 handle_ebadf(self.0.write_all_vectored(bufs), ())
146 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
147 handle_ebadf(self.0.write_fmt(fmt), ())
151 impl Write for StderrRaw {
152 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
153 handle_ebadf(self.0.write(buf), buf.len())
156 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
157 let total = bufs.iter().map(|b| b.len()).sum();
158 handle_ebadf(self.0.write_vectored(bufs), total)
162 fn is_write_vectored(&self) -> bool {
163 self.0.is_write_vectored()
166 fn flush(&mut self) -> io::Result<()> {
167 handle_ebadf(self.0.flush(), ())
170 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
171 handle_ebadf(self.0.write_all(buf), ())
174 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
175 handle_ebadf(self.0.write_all_vectored(bufs), ())
178 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
179 handle_ebadf(self.0.write_fmt(fmt), ())
183 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
185 Err(ref e) if stdio::is_ebadf(e) => Ok(default),
190 /// A handle to the standard input stream of a process.
192 /// Each handle is a shared reference to a global buffer of input data to this
193 /// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
194 /// (e.g., `.lines()`). Reads to this handle are otherwise locked with respect
197 /// This handle implements the `Read` trait, but beware that concurrent reads
198 /// of `Stdin` must be executed with care.
200 /// Created by the [`io::stdin`] method.
202 /// [`io::stdin`]: stdin
204 /// ### Note: Windows Portability Considerations
206 /// When operating in a console, the Windows implementation of this stream does not support
207 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
210 /// In a process with a detached console, such as one using
211 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
212 /// the contained handle will be null. In such cases, the standard library's `Read` and
213 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
214 /// standard library or via raw Windows API calls, will fail.
221 /// fn main() -> io::Result<()> {
222 /// let mut buffer = String::new();
223 /// let stdin = io::stdin(); // We get `Stdin` here.
224 /// stdin.read_line(&mut buffer)?;
228 #[stable(feature = "rust1", since = "1.0.0")]
230 inner: &'static Mutex<BufReader<StdinRaw>>,
233 /// A locked reference to the [`Stdin`] handle.
235 /// This handle implements both the [`Read`] and [`BufRead`] traits, and
236 /// is constructed via the [`Stdin::lock`] method.
238 /// ### Note: Windows Portability Considerations
240 /// When operating in a console, the Windows implementation of this stream does not support
241 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
244 /// In a process with a detached console, such as one using
245 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
246 /// the contained handle will be null. In such cases, the standard library's `Read` and
247 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
248 /// standard library or via raw Windows API calls, will fail.
253 /// use std::io::{self, BufRead};
255 /// fn main() -> io::Result<()> {
256 /// let mut buffer = String::new();
257 /// let stdin = io::stdin(); // We get `Stdin` here.
259 /// let mut handle = stdin.lock(); // We get `StdinLock` here.
260 /// handle.read_line(&mut buffer)?;
261 /// } // `StdinLock` is dropped here.
265 #[must_use = "if unused stdin will immediately unlock"]
266 #[stable(feature = "rust1", since = "1.0.0")]
267 pub struct StdinLock<'a> {
268 inner: MutexGuard<'a, BufReader<StdinRaw>>,
271 /// Constructs a new handle to the standard input of the current process.
273 /// Each handle returned is a reference to a shared global buffer whose access
274 /// is synchronized via a mutex. If you need more explicit control over
275 /// locking, see the [`Stdin::lock`] method.
277 /// ### Note: Windows Portability Considerations
279 /// When operating in a console, the Windows implementation of this stream does not support
280 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
283 /// In a process with a detached console, such as one using
284 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
285 /// the contained handle will be null. In such cases, the standard library's `Read` and
286 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
287 /// standard library or via raw Windows API calls, will fail.
291 /// Using implicit synchronization:
296 /// fn main() -> io::Result<()> {
297 /// let mut buffer = String::new();
298 /// io::stdin().read_line(&mut buffer)?;
303 /// Using explicit synchronization:
306 /// use std::io::{self, BufRead};
308 /// fn main() -> io::Result<()> {
309 /// let mut buffer = String::new();
310 /// let stdin = io::stdin();
311 /// let mut handle = stdin.lock();
313 /// handle.read_line(&mut buffer)?;
318 #[stable(feature = "rust1", since = "1.0.0")]
319 pub fn stdin() -> Stdin {
320 static INSTANCE: OnceLock<Mutex<BufReader<StdinRaw>>> = OnceLock::new();
322 inner: INSTANCE.get_or_init(|| {
323 Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin_raw()))
329 /// Locks this handle to the standard input stream, returning a readable
332 /// The lock is released when the returned lock goes out of scope. The
333 /// returned guard also implements the [`Read`] and [`BufRead`] traits for
334 /// accessing the underlying data.
339 /// use std::io::{self, BufRead};
341 /// fn main() -> io::Result<()> {
342 /// let mut buffer = String::new();
343 /// let stdin = io::stdin();
344 /// let mut handle = stdin.lock();
346 /// handle.read_line(&mut buffer)?;
350 #[stable(feature = "rust1", since = "1.0.0")]
351 pub fn lock(&self) -> StdinLock<'static> {
352 // Locks this handle with 'static lifetime. This depends on the
353 // implementation detail that the underlying `Mutex` is static.
354 StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
357 /// Locks this handle and reads a line of input, appending it to the specified buffer.
359 /// For detailed semantics of this method, see the documentation on
360 /// [`BufRead::read_line`].
367 /// let mut input = String::new();
368 /// match io::stdin().read_line(&mut input) {
370 /// println!("{n} bytes read");
371 /// println!("{input}");
373 /// Err(error) => println!("error: {error}"),
377 /// You can run the example one of two ways:
379 /// - Pipe some text to it, e.g., `printf foo | path/to/executable`
380 /// - Give it text interactively by running the executable directly,
381 /// in which case it will wait for the Enter key to be pressed before
383 #[stable(feature = "rust1", since = "1.0.0")]
384 pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
385 self.lock().read_line(buf)
388 /// Consumes this handle and returns an iterator over input lines.
390 /// For detailed semantics of this method, see the documentation on
391 /// [`BufRead::lines`].
398 /// let lines = io::stdin().lines();
399 /// for line in lines {
400 /// println!("got a line: {}", line.unwrap());
403 #[must_use = "`self` will be dropped if the result is not used"]
404 #[stable(feature = "stdin_forwarders", since = "1.62.0")]
405 pub fn lines(self) -> Lines<StdinLock<'static>> {
410 #[stable(feature = "std_debug", since = "1.16.0")]
411 impl fmt::Debug for Stdin {
412 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
413 f.debug_struct("Stdin").finish_non_exhaustive()
417 #[stable(feature = "rust1", since = "1.0.0")]
418 impl Read for Stdin {
419 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
420 self.lock().read(buf)
422 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
423 self.lock().read_vectored(bufs)
426 fn is_read_vectored(&self) -> bool {
427 self.lock().is_read_vectored()
429 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
430 self.lock().read_to_end(buf)
432 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
433 self.lock().read_to_string(buf)
435 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
436 self.lock().read_exact(buf)
440 // only used by platform-dependent io::copy specializations, i.e. unused on some platforms
441 #[cfg(any(target_os = "linux", target_os = "android"))]
443 pub(crate) fn as_mut_buf(&mut self) -> &mut BufReader<impl Read> {
448 #[stable(feature = "rust1", since = "1.0.0")]
449 impl Read for StdinLock<'_> {
450 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
454 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
455 self.inner.read_vectored(bufs)
459 fn is_read_vectored(&self) -> bool {
460 self.inner.is_read_vectored()
463 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
464 self.inner.read_to_end(buf)
467 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
468 self.inner.read_to_string(buf)
471 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
472 self.inner.read_exact(buf)
476 #[stable(feature = "rust1", since = "1.0.0")]
477 impl BufRead for StdinLock<'_> {
478 fn fill_buf(&mut self) -> io::Result<&[u8]> {
479 self.inner.fill_buf()
482 fn consume(&mut self, n: usize) {
483 self.inner.consume(n)
486 fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
487 self.inner.read_until(byte, buf)
490 fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
491 self.inner.read_line(buf)
495 #[stable(feature = "std_debug", since = "1.16.0")]
496 impl fmt::Debug for StdinLock<'_> {
497 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
498 f.debug_struct("StdinLock").finish_non_exhaustive()
502 /// A handle to the global standard output stream of the current process.
504 /// Each handle shares a global buffer of data to be written to the standard
505 /// output stream. Access is also synchronized via a lock and explicit control
506 /// over locking is available via the [`lock`] method.
508 /// Created by the [`io::stdout`] method.
510 /// ### Note: Windows Portability Considerations
512 /// When operating in a console, the Windows implementation of this stream does not support
513 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
516 /// In a process with a detached console, such as one using
517 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
518 /// the contained handle will be null. In such cases, the standard library's `Read` and
519 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
520 /// standard library or via raw Windows API calls, will fail.
522 /// [`lock`]: Stdout::lock
523 /// [`io::stdout`]: stdout
524 #[stable(feature = "rust1", since = "1.0.0")]
526 // FIXME: this should be LineWriter or BufWriter depending on the state of
527 // stdout (tty or not). Note that if this is not line buffered it
528 // should also flush-on-panic or some form of flush-on-abort.
529 inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
532 /// A locked reference to the [`Stdout`] handle.
534 /// This handle implements the [`Write`] trait, and is constructed via
535 /// the [`Stdout::lock`] method. See its documentation for more.
537 /// ### Note: Windows Portability Considerations
539 /// When operating in a console, the Windows implementation of this stream does not support
540 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
543 /// In a process with a detached console, such as one using
544 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
545 /// the contained handle will be null. In such cases, the standard library's `Read` and
546 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
547 /// standard library or via raw Windows API calls, will fail.
548 #[must_use = "if unused stdout will immediately unlock"]
549 #[stable(feature = "rust1", since = "1.0.0")]
550 pub struct StdoutLock<'a> {
551 inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
554 static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
556 /// Constructs a new handle to the standard output of the current process.
558 /// Each handle returned is a reference to a shared global buffer whose access
559 /// is synchronized via a mutex. If you need more explicit control over
560 /// locking, see the [`Stdout::lock`] method.
562 /// ### Note: Windows Portability Considerations
564 /// When operating in a console, the Windows implementation of this stream does not support
565 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
568 /// In a process with a detached console, such as one using
569 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
570 /// the contained handle will be null. In such cases, the standard library's `Read` and
571 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
572 /// standard library or via raw Windows API calls, will fail.
576 /// Using implicit synchronization:
579 /// use std::io::{self, Write};
581 /// fn main() -> io::Result<()> {
582 /// io::stdout().write_all(b"hello world")?;
588 /// Using explicit synchronization:
591 /// use std::io::{self, Write};
593 /// fn main() -> io::Result<()> {
594 /// let stdout = io::stdout();
595 /// let mut handle = stdout.lock();
597 /// handle.write_all(b"hello world")?;
603 #[stable(feature = "rust1", since = "1.0.0")]
604 pub fn stdout() -> Stdout {
607 .get_or_init(|| ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))),
611 // Flush the data and disable buffering during shutdown
612 // by replacing the line writer by one with zero
613 // buffering capacity.
615 let mut initialized = false;
616 let stdout = STDOUT.get_or_init(|| {
618 ReentrantMutex::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
622 // The buffer was previously initialized, overwrite it here.
623 // We use try_lock() instead of lock(), because someone
624 // might have leaked a StdoutLock, which would
625 // otherwise cause a deadlock here.
626 if let Some(lock) = stdout.try_lock() {
627 *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
633 /// Locks this handle to the standard output stream, returning a writable
636 /// The lock is released when the returned lock goes out of scope. The
637 /// returned guard also implements the `Write` trait for writing data.
642 /// use std::io::{self, Write};
644 /// fn main() -> io::Result<()> {
645 /// let mut stdout = io::stdout().lock();
647 /// stdout.write_all(b"hello world")?;
652 #[stable(feature = "rust1", since = "1.0.0")]
653 pub fn lock(&self) -> StdoutLock<'static> {
654 // Locks this handle with 'static lifetime. This depends on the
655 // implementation detail that the underlying `ReentrantMutex` is
657 StdoutLock { inner: self.inner.lock() }
661 #[stable(feature = "std_debug", since = "1.16.0")]
662 impl fmt::Debug for Stdout {
663 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
664 f.debug_struct("Stdout").finish_non_exhaustive()
668 #[stable(feature = "rust1", since = "1.0.0")]
669 impl Write for Stdout {
670 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
673 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
674 (&*self).write_vectored(bufs)
677 fn is_write_vectored(&self) -> bool {
678 io::Write::is_write_vectored(&&*self)
680 fn flush(&mut self) -> io::Result<()> {
683 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
684 (&*self).write_all(buf)
686 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
687 (&*self).write_all_vectored(bufs)
689 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
690 (&*self).write_fmt(args)
694 #[stable(feature = "write_mt", since = "1.48.0")]
695 impl Write for &Stdout {
696 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
697 self.lock().write(buf)
699 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
700 self.lock().write_vectored(bufs)
703 fn is_write_vectored(&self) -> bool {
704 self.lock().is_write_vectored()
706 fn flush(&mut self) -> io::Result<()> {
709 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
710 self.lock().write_all(buf)
712 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
713 self.lock().write_all_vectored(bufs)
715 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
716 self.lock().write_fmt(args)
720 #[stable(feature = "rust1", since = "1.0.0")]
721 impl Write for StdoutLock<'_> {
722 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
723 self.inner.borrow_mut().write(buf)
725 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
726 self.inner.borrow_mut().write_vectored(bufs)
729 fn is_write_vectored(&self) -> bool {
730 self.inner.borrow_mut().is_write_vectored()
732 fn flush(&mut self) -> io::Result<()> {
733 self.inner.borrow_mut().flush()
735 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
736 self.inner.borrow_mut().write_all(buf)
738 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
739 self.inner.borrow_mut().write_all_vectored(bufs)
743 #[stable(feature = "std_debug", since = "1.16.0")]
744 impl fmt::Debug for StdoutLock<'_> {
745 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
746 f.debug_struct("StdoutLock").finish_non_exhaustive()
750 /// A handle to the standard error stream of a process.
752 /// For more information, see the [`io::stderr`] method.
754 /// [`io::stderr`]: stderr
756 /// ### Note: Windows Portability Considerations
758 /// When operating in a console, the Windows implementation of this stream does not support
759 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
762 /// In a process with a detached console, such as one using
763 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
764 /// the contained handle will be null. In such cases, the standard library's `Read` and
765 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
766 /// standard library or via raw Windows API calls, will fail.
767 #[stable(feature = "rust1", since = "1.0.0")]
769 inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
772 /// A locked reference to the [`Stderr`] handle.
774 /// This handle implements the [`Write`] trait and is constructed via
775 /// the [`Stderr::lock`] method. See its documentation for more.
777 /// ### Note: Windows Portability Considerations
779 /// When operating in a console, the Windows implementation of this stream does not support
780 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
783 /// In a process with a detached console, such as one using
784 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
785 /// the contained handle will be null. In such cases, the standard library's `Read` and
786 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
787 /// standard library or via raw Windows API calls, will fail.
788 #[must_use = "if unused stderr will immediately unlock"]
789 #[stable(feature = "rust1", since = "1.0.0")]
790 pub struct StderrLock<'a> {
791 inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
794 /// Constructs a new handle to the standard error of the current process.
796 /// This handle is not buffered.
798 /// ### Note: Windows Portability Considerations
800 /// When operating in a console, the Windows implementation of this stream does not support
801 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
804 /// In a process with a detached console, such as one using
805 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
806 /// the contained handle will be null. In such cases, the standard library's `Read` and
807 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
808 /// standard library or via raw Windows API calls, will fail.
812 /// Using implicit synchronization:
815 /// use std::io::{self, Write};
817 /// fn main() -> io::Result<()> {
818 /// io::stderr().write_all(b"hello world")?;
824 /// Using explicit synchronization:
827 /// use std::io::{self, Write};
829 /// fn main() -> io::Result<()> {
830 /// let stderr = io::stderr();
831 /// let mut handle = stderr.lock();
833 /// handle.write_all(b"hello world")?;
839 #[stable(feature = "rust1", since = "1.0.0")]
840 pub fn stderr() -> Stderr {
841 // Note that unlike `stdout()` we don't use `at_exit` here to register a
842 // destructor. Stderr is not buffered, so there's no need to run a
843 // destructor for flushing the buffer
844 static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
845 ReentrantMutex::new(RefCell::new(stderr_raw()));
847 Stderr { inner: &INSTANCE }
851 /// Locks this handle to the standard error stream, returning a writable
854 /// The lock is released when the returned lock goes out of scope. The
855 /// returned guard also implements the [`Write`] trait for writing data.
860 /// use std::io::{self, Write};
862 /// fn foo() -> io::Result<()> {
863 /// let stderr = io::stderr();
864 /// let mut handle = stderr.lock();
866 /// handle.write_all(b"hello world")?;
871 #[stable(feature = "rust1", since = "1.0.0")]
872 pub fn lock(&self) -> StderrLock<'static> {
873 // Locks this handle with 'static lifetime. This depends on the
874 // implementation detail that the underlying `ReentrantMutex` is
876 StderrLock { inner: self.inner.lock() }
880 #[stable(feature = "std_debug", since = "1.16.0")]
881 impl fmt::Debug for Stderr {
882 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
883 f.debug_struct("Stderr").finish_non_exhaustive()
887 #[stable(feature = "rust1", since = "1.0.0")]
888 impl Write for Stderr {
889 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
892 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
893 (&*self).write_vectored(bufs)
896 fn is_write_vectored(&self) -> bool {
897 io::Write::is_write_vectored(&&*self)
899 fn flush(&mut self) -> io::Result<()> {
902 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
903 (&*self).write_all(buf)
905 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
906 (&*self).write_all_vectored(bufs)
908 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
909 (&*self).write_fmt(args)
913 #[stable(feature = "write_mt", since = "1.48.0")]
914 impl Write for &Stderr {
915 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
916 self.lock().write(buf)
918 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
919 self.lock().write_vectored(bufs)
922 fn is_write_vectored(&self) -> bool {
923 self.lock().is_write_vectored()
925 fn flush(&mut self) -> io::Result<()> {
928 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
929 self.lock().write_all(buf)
931 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
932 self.lock().write_all_vectored(bufs)
934 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
935 self.lock().write_fmt(args)
939 #[stable(feature = "rust1", since = "1.0.0")]
940 impl Write for StderrLock<'_> {
941 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
942 self.inner.borrow_mut().write(buf)
944 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
945 self.inner.borrow_mut().write_vectored(bufs)
948 fn is_write_vectored(&self) -> bool {
949 self.inner.borrow_mut().is_write_vectored()
951 fn flush(&mut self) -> io::Result<()> {
952 self.inner.borrow_mut().flush()
954 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
955 self.inner.borrow_mut().write_all(buf)
957 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
958 self.inner.borrow_mut().write_all_vectored(bufs)
962 #[stable(feature = "std_debug", since = "1.16.0")]
963 impl fmt::Debug for StderrLock<'_> {
964 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
965 f.debug_struct("StderrLock").finish_non_exhaustive()
969 /// Sets the thread-local output capture buffer and returns the old one.
971 feature = "internal_output_capture",
972 reason = "this function is meant for use in the test crate \
973 and may disappear in the future",
977 pub fn set_output_capture(sink: Option<LocalStream>) -> Option<LocalStream> {
978 if sink.is_none() && !OUTPUT_CAPTURE_USED.load(Ordering::Relaxed) {
979 // OUTPUT_CAPTURE is definitely None since OUTPUT_CAPTURE_USED is false.
982 OUTPUT_CAPTURE_USED.store(true, Ordering::Relaxed);
983 OUTPUT_CAPTURE.with(move |slot| slot.replace(sink))
986 /// Write `args` to the capture buffer if enabled and possible, or `global_s`
987 /// otherwise. `label` identifies the stream in a panic message.
989 /// This function is used to print error messages, so it takes extra
990 /// care to avoid causing a panic when `OUTPUT_CAPTURE` is unusable.
991 /// For instance, if the TLS key for output capturing is already destroyed, or
992 /// if the local stream is in use by another thread, it will just fall back to
993 /// the global stream.
995 /// However, if the actual I/O causes an error, this function does panic.
997 /// Writing to non-blocking stdout/stderr can cause an error, which will lead
998 /// this function to panic.
999 fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str)
1003 if print_to_buffer_if_capture_used(args) {
1004 // Successfully wrote to capture buffer.
1008 if let Err(e) = global_s().write_fmt(args) {
1009 panic!("failed printing to {label}: {e}");
1013 fn print_to_buffer_if_capture_used(args: fmt::Arguments<'_>) -> bool {
1014 OUTPUT_CAPTURE_USED.load(Ordering::Relaxed)
1015 && OUTPUT_CAPTURE.try_with(|s| {
1016 // Note that we completely remove a local sink to write to in case
1017 // our printing recursively panics/prints, so the recursive
1018 // panic/print goes to the global sink instead of our local sink.
1020 let _ = w.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(args);
1026 /// Used by impl Termination for Result to print error after `main` or a test
1027 /// has returned. Should avoid panicking, although we can't help it if one of
1028 /// the Display impls inside args decides to.
1029 pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) {
1030 if print_to_buffer_if_capture_used(args) {
1034 // Ignore error if the write fails, for example because stderr is already
1035 // closed. There is not much point panicking at this point.
1036 let _ = stderr().write_fmt(args);
1039 /// Trait to determine if a descriptor/handle refers to a terminal/tty.
1040 #[unstable(feature = "is_terminal", issue = "98070")]
1041 pub trait IsTerminal: crate::sealed::Sealed {
1042 /// Returns `true` if the descriptor/handle refers to a terminal/tty.
1044 /// On platforms where Rust does not know how to detect a terminal yet, this will return
1045 /// `false`. This will also return `false` if an unexpected error occurred, such as from
1046 /// passing an invalid file descriptor.
1047 fn is_terminal(&self) -> bool;
1050 macro_rules! impl_is_terminal {
1051 ($($t:ty),*$(,)?) => {$(
1052 #[unstable(feature = "sealed", issue = "none")]
1053 impl crate::sealed::Sealed for $t {}
1055 #[unstable(feature = "is_terminal", issue = "98070")]
1056 impl IsTerminal for $t {
1058 fn is_terminal(&self) -> bool {
1059 crate::sys::io::is_terminal(self)
1065 impl_is_terminal!(File, Stdin, StdinLock<'_>, Stdout, StdoutLock<'_>, Stderr, StderrLock<'_>);
1068 feature = "print_internals",
1069 reason = "implementation detail which may disappear or be replaced at any time",
1074 pub fn _print(args: fmt::Arguments<'_>) {
1075 print_to(args, stdout, "stdout");
1079 feature = "print_internals",
1080 reason = "implementation detail which may disappear or be replaced at any time",
1085 pub fn _eprint(args: fmt::Arguments<'_>) {
1086 print_to(args, stderr, "stderr");
1090 pub use realstd::io::{_eprint, _print};