1 #![cfg_attr(test, allow(unused))]
6 use crate::io::prelude::*;
8 use crate::cell::{Cell, RefCell};
10 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: Pin<&'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 {
606 inner: Pin::static_ref(&STDOUT).get_or_init_pin(
607 || unsafe { ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))) },
608 |mutex| unsafe { mutex.init() },
614 if let Some(instance) = STDOUT.get() {
615 // Flush the data and disable buffering during shutdown
616 // by replacing the line writer by one with zero
617 // buffering capacity.
618 // We use try_lock() instead of lock(), because someone
619 // might have leaked a StdoutLock, which would
620 // otherwise cause a deadlock here.
621 if let Some(lock) = Pin::static_ref(instance).try_lock() {
622 *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
628 /// Locks this handle to the standard output stream, returning a writable
631 /// The lock is released when the returned lock goes out of scope. The
632 /// returned guard also implements the `Write` trait for writing data.
637 /// use std::io::{self, Write};
639 /// fn main() -> io::Result<()> {
640 /// let mut stdout = io::stdout().lock();
642 /// stdout.write_all(b"hello world")?;
647 #[stable(feature = "rust1", since = "1.0.0")]
648 pub fn lock(&self) -> StdoutLock<'static> {
649 // Locks this handle with 'static lifetime. This depends on the
650 // implementation detail that the underlying `ReentrantMutex` is
652 StdoutLock { inner: self.inner.lock() }
656 #[stable(feature = "std_debug", since = "1.16.0")]
657 impl fmt::Debug for Stdout {
658 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
659 f.debug_struct("Stdout").finish_non_exhaustive()
663 #[stable(feature = "rust1", since = "1.0.0")]
664 impl Write for Stdout {
665 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
668 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
669 (&*self).write_vectored(bufs)
672 fn is_write_vectored(&self) -> bool {
673 io::Write::is_write_vectored(&&*self)
675 fn flush(&mut self) -> io::Result<()> {
678 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
679 (&*self).write_all(buf)
681 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
682 (&*self).write_all_vectored(bufs)
684 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
685 (&*self).write_fmt(args)
689 #[stable(feature = "write_mt", since = "1.48.0")]
690 impl Write for &Stdout {
691 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
692 self.lock().write(buf)
694 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
695 self.lock().write_vectored(bufs)
698 fn is_write_vectored(&self) -> bool {
699 self.lock().is_write_vectored()
701 fn flush(&mut self) -> io::Result<()> {
704 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
705 self.lock().write_all(buf)
707 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
708 self.lock().write_all_vectored(bufs)
710 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
711 self.lock().write_fmt(args)
715 #[stable(feature = "rust1", since = "1.0.0")]
716 impl Write for StdoutLock<'_> {
717 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
718 self.inner.borrow_mut().write(buf)
720 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
721 self.inner.borrow_mut().write_vectored(bufs)
724 fn is_write_vectored(&self) -> bool {
725 self.inner.borrow_mut().is_write_vectored()
727 fn flush(&mut self) -> io::Result<()> {
728 self.inner.borrow_mut().flush()
730 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
731 self.inner.borrow_mut().write_all(buf)
733 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
734 self.inner.borrow_mut().write_all_vectored(bufs)
738 #[stable(feature = "std_debug", since = "1.16.0")]
739 impl fmt::Debug for StdoutLock<'_> {
740 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
741 f.debug_struct("StdoutLock").finish_non_exhaustive()
745 /// A handle to the standard error stream of a process.
747 /// For more information, see the [`io::stderr`] method.
749 /// [`io::stderr`]: stderr
751 /// ### Note: Windows Portability Considerations
753 /// When operating in a console, the Windows implementation of this stream does not support
754 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
757 /// In a process with a detached console, such as one using
758 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
759 /// the contained handle will be null. In such cases, the standard library's `Read` and
760 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
761 /// standard library or via raw Windows API calls, will fail.
762 #[stable(feature = "rust1", since = "1.0.0")]
764 inner: Pin<&'static ReentrantMutex<RefCell<StderrRaw>>>,
767 /// A locked reference to the [`Stderr`] handle.
769 /// This handle implements the [`Write`] trait and is constructed via
770 /// the [`Stderr::lock`] method. See its documentation for more.
772 /// ### Note: Windows Portability Considerations
774 /// When operating in a console, the Windows implementation of this stream does not support
775 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
778 /// In a process with a detached console, such as one using
779 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
780 /// the contained handle will be null. In such cases, the standard library's `Read` and
781 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
782 /// standard library or via raw Windows API calls, will fail.
783 #[must_use = "if unused stderr will immediately unlock"]
784 #[stable(feature = "rust1", since = "1.0.0")]
785 pub struct StderrLock<'a> {
786 inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
789 /// Constructs a new handle to the standard error of the current process.
791 /// This handle is not buffered.
793 /// ### Note: Windows Portability Considerations
795 /// When operating in a console, the Windows implementation of this stream does not support
796 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
799 /// In a process with a detached console, such as one using
800 /// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
801 /// the contained handle will be null. In such cases, the standard library's `Read` and
802 /// `Write` will do nothing and silently succeed. All other I/O operations, via the
803 /// standard library or via raw Windows API calls, will fail.
807 /// Using implicit synchronization:
810 /// use std::io::{self, Write};
812 /// fn main() -> io::Result<()> {
813 /// io::stderr().write_all(b"hello world")?;
819 /// Using explicit synchronization:
822 /// use std::io::{self, Write};
824 /// fn main() -> io::Result<()> {
825 /// let stderr = io::stderr();
826 /// let mut handle = stderr.lock();
828 /// handle.write_all(b"hello world")?;
834 #[stable(feature = "rust1", since = "1.0.0")]
835 pub fn stderr() -> Stderr {
836 // Note that unlike `stdout()` we don't use `at_exit` here to register a
837 // destructor. Stderr is not buffered , so there's no need to run a
838 // destructor for flushing the buffer
839 static INSTANCE: OnceLock<ReentrantMutex<RefCell<StderrRaw>>> = OnceLock::new();
842 inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
843 || unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) },
844 |mutex| unsafe { mutex.init() },
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 `local_s` is unusable.
990 /// For instance, if the TLS key for the local stream is
991 /// already destroyed, or if the local stream is locked by another
992 /// thread, it will just fall back to the global stream.
994 /// However, if the actual I/O causes an error, this function does panic.
995 fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str)
999 if OUTPUT_CAPTURE_USED.load(Ordering::Relaxed)
1000 && OUTPUT_CAPTURE.try_with(|s| {
1001 // Note that we completely remove a local sink to write to in case
1002 // our printing recursively panics/prints, so the recursive
1003 // panic/print goes to the global sink instead of our local sink.
1005 let _ = w.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(args);
1010 // Successfully wrote to capture buffer.
1014 if let Err(e) = global_s().write_fmt(args) {
1015 panic!("failed printing to {label}: {e}");
1020 feature = "print_internals",
1021 reason = "implementation detail which may disappear or be replaced at any time",
1026 pub fn _print(args: fmt::Arguments<'_>) {
1027 print_to(args, stdout, "stdout");
1031 feature = "print_internals",
1032 reason = "implementation detail which may disappear or be replaced at any time",
1037 pub fn _eprint(args: fmt::Arguments<'_>) {
1038 print_to(args, stderr, "stderr");
1042 pub use realstd::io::{_eprint, _print};