1 #![cfg_attr(test, allow(unused))]
3 use crate::io::prelude::*;
5 use crate::cell::RefCell;
7 use crate::io::lazy::Lazy;
8 use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter};
9 use crate::sync::{Arc, Mutex, MutexGuard, Once};
10 use crate::sys::stdio;
11 use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
12 use crate::thread::LocalKey;
15 /// Stdout used by print! and println! macros
16 static LOCAL_STDOUT: RefCell<Option<Box<dyn Write + Send>>> = {
22 /// Stderr used by eprint! and eprintln! macros, and panics
23 static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
28 /// A handle to a raw instance of the standard input stream of this process.
30 /// This handle is not synchronized or buffered in any fashion. Constructed via
31 /// the `std::io::stdio::stdin_raw` function.
32 struct StdinRaw(stdio::Stdin);
34 /// A handle to a raw instance of the standard output stream of this process.
36 /// This handle is not synchronized or buffered in any fashion. Constructed via
37 /// the `std::io::stdio::stdout_raw` function.
38 struct StdoutRaw(stdio::Stdout);
40 /// A handle to a raw instance of the standard output stream of this process.
42 /// This handle is not synchronized or buffered in any fashion. Constructed via
43 /// the `std::io::stdio::stderr_raw` function.
44 struct StderrRaw(stdio::Stderr);
46 /// Constructs a new raw handle to the standard input of this process.
48 /// The returned handle does not interact with any other handles created nor
49 /// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
50 /// handles is **not** available to raw handles returned from this function.
52 /// The returned handle has no external synchronization or buffering.
53 #[unstable(feature = "libstd_sys_internals", issue = "none")]
54 const fn stdin_raw() -> StdinRaw {
55 StdinRaw(stdio::Stdin::new())
58 /// Constructs a new raw handle to the standard output stream of this process.
60 /// The returned handle does not interact with any other handles created nor
61 /// handles returned by `std::io::stdout`. Note that data is buffered by the
62 /// `std::io::stdout` handles so writes which happen via this raw handle may
63 /// appear before previous writes.
65 /// The returned handle has no external synchronization or buffering layered on
67 #[unstable(feature = "libstd_sys_internals", issue = "none")]
68 const fn stdout_raw() -> StdoutRaw {
69 StdoutRaw(stdio::Stdout::new())
72 /// Constructs a new raw handle to the standard error stream of this process.
74 /// The returned handle does not interact with any other handles created nor
75 /// handles returned by `std::io::stderr`.
77 /// The returned handle has no external synchronization or buffering layered on
79 #[unstable(feature = "libstd_sys_internals", issue = "none")]
80 const fn stderr_raw() -> StderrRaw {
81 StderrRaw(stdio::Stderr::new())
84 impl Read for StdinRaw {
85 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
86 handle_ebadf(self.0.read(buf), 0)
89 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
90 handle_ebadf(self.0.read_vectored(bufs), 0)
94 fn is_read_vectored(&self) -> bool {
95 self.0.is_read_vectored()
99 unsafe fn initializer(&self) -> Initializer {
103 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
104 handle_ebadf(self.0.read_to_end(buf), 0)
107 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
108 handle_ebadf(self.0.read_to_string(buf), 0)
112 impl Write for StdoutRaw {
113 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
114 handle_ebadf(self.0.write(buf), buf.len())
117 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
118 let total = bufs.iter().map(|b| b.len()).sum();
119 handle_ebadf(self.0.write_vectored(bufs), total)
123 fn is_write_vectored(&self) -> bool {
124 self.0.is_write_vectored()
127 fn flush(&mut self) -> io::Result<()> {
128 handle_ebadf(self.0.flush(), ())
131 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
132 handle_ebadf(self.0.write_all(buf), ())
135 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
136 handle_ebadf(self.0.write_all_vectored(bufs), ())
139 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
140 handle_ebadf(self.0.write_fmt(fmt), ())
144 impl Write for StderrRaw {
145 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
146 handle_ebadf(self.0.write(buf), buf.len())
149 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
150 let total = bufs.iter().map(|b| b.len()).sum();
151 handle_ebadf(self.0.write_vectored(bufs), total)
155 fn is_write_vectored(&self) -> bool {
156 self.0.is_write_vectored()
159 fn flush(&mut self) -> io::Result<()> {
160 handle_ebadf(self.0.flush(), ())
163 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
164 handle_ebadf(self.0.write_all(buf), ())
167 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
168 handle_ebadf(self.0.write_all_vectored(bufs), ())
171 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
172 handle_ebadf(self.0.write_fmt(fmt), ())
176 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
178 Err(ref e) if stdio::is_ebadf(e) => Ok(default),
183 /// A handle to the standard input stream of a process.
185 /// Each handle is a shared reference to a global buffer of input data to this
186 /// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
187 /// (e.g., `.lines()`). Reads to this handle are otherwise locked with respect
190 /// This handle implements the `Read` trait, but beware that concurrent reads
191 /// of `Stdin` must be executed with care.
193 /// Created by the [`io::stdin`] method.
195 /// [`io::stdin`]: stdin
197 /// ### Note: Windows Portability Consideration
199 /// When operating in a console, the Windows implementation of this stream does not support
200 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
206 /// use std::io::{self, Read};
208 /// fn main() -> io::Result<()> {
209 /// let mut buffer = String::new();
210 /// let mut stdin = io::stdin(); // We get `Stdin` here.
211 /// stdin.read_to_string(&mut buffer)?;
215 #[stable(feature = "rust1", since = "1.0.0")]
217 inner: Arc<Mutex<BufReader<StdinRaw>>>,
220 /// A locked reference to the `Stdin` handle.
222 /// This handle implements both the [`Read`] and [`BufRead`] traits, and
223 /// is constructed via the [`Stdin::lock`] method.
225 /// ### Note: Windows Portability Consideration
227 /// When operating in a console, the Windows implementation of this stream does not support
228 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
234 /// use std::io::{self, Read};
236 /// fn main() -> io::Result<()> {
237 /// let mut buffer = String::new();
238 /// let stdin = io::stdin(); // We get `Stdin` here.
240 /// let mut stdin_lock = stdin.lock(); // We get `StdinLock` here.
241 /// stdin_lock.read_to_string(&mut buffer)?;
242 /// } // `StdinLock` is dropped here.
246 #[stable(feature = "rust1", since = "1.0.0")]
247 pub struct StdinLock<'a> {
248 inner: MutexGuard<'a, BufReader<StdinRaw>>,
251 /// Constructs a new handle to the standard input of the current process.
253 /// Each handle returned is a reference to a shared global buffer whose access
254 /// is synchronized via a mutex. If you need more explicit control over
255 /// locking, see the [`Stdin::lock`] method.
257 /// ### Note: Windows Portability Consideration
258 /// When operating in a console, the Windows implementation of this stream does not support
259 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
264 /// Using implicit synchronization:
267 /// use std::io::{self, Read};
269 /// fn main() -> io::Result<()> {
270 /// let mut buffer = String::new();
271 /// io::stdin().read_to_string(&mut buffer)?;
276 /// Using explicit synchronization:
279 /// use std::io::{self, Read};
281 /// fn main() -> io::Result<()> {
282 /// let mut buffer = String::new();
283 /// let stdin = io::stdin();
284 /// let mut handle = stdin.lock();
286 /// handle.read_to_string(&mut buffer)?;
290 #[stable(feature = "rust1", since = "1.0.0")]
291 pub fn stdin() -> Stdin {
292 static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = Lazy::new();
294 inner: unsafe { INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown") },
297 fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
298 // This must not reentrantly access `INSTANCE`
299 let stdin = stdin_raw();
300 Arc::new(Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin)))
305 /// Locks this handle to the standard input stream, returning a readable
308 /// The lock is released when the returned lock goes out of scope. The
309 /// returned guard also implements the [`Read`] and [`BufRead`] traits for
310 /// accessing the underlying data.
315 /// use std::io::{self, Read};
317 /// fn main() -> io::Result<()> {
318 /// let mut buffer = String::new();
319 /// let stdin = io::stdin();
320 /// let mut handle = stdin.lock();
322 /// handle.read_to_string(&mut buffer)?;
326 #[stable(feature = "rust1", since = "1.0.0")]
327 pub fn lock(&self) -> StdinLock<'_> {
328 StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
331 /// Locks this handle and reads a line of input, appending it to the specified buffer.
333 /// For detailed semantics of this method, see the documentation on
334 /// [`BufRead::read_line`].
341 /// let mut input = String::new();
342 /// match io::stdin().read_line(&mut input) {
344 /// println!("{} bytes read", n);
345 /// println!("{}", input);
347 /// Err(error) => println!("error: {}", error),
351 /// You can run the example one of two ways:
353 /// - Pipe some text to it, e.g., `printf foo | path/to/executable`
354 /// - Give it text interactively by running the executable directly,
355 /// in which case it will wait for the Enter key to be pressed before
357 #[stable(feature = "rust1", since = "1.0.0")]
358 pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
359 self.lock().read_line(buf)
363 #[stable(feature = "std_debug", since = "1.16.0")]
364 impl fmt::Debug for Stdin {
365 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366 f.pad("Stdin { .. }")
370 #[stable(feature = "rust1", since = "1.0.0")]
371 impl Read for Stdin {
372 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
373 self.lock().read(buf)
375 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
376 self.lock().read_vectored(bufs)
379 fn is_read_vectored(&self) -> bool {
380 self.lock().is_read_vectored()
383 unsafe fn initializer(&self) -> Initializer {
386 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
387 self.lock().read_to_end(buf)
389 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
390 self.lock().read_to_string(buf)
392 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
393 self.lock().read_exact(buf)
397 #[stable(feature = "rust1", since = "1.0.0")]
398 impl Read for StdinLock<'_> {
399 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
403 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
404 self.inner.read_vectored(bufs)
408 fn is_read_vectored(&self) -> bool {
409 self.inner.is_read_vectored()
413 unsafe fn initializer(&self) -> Initializer {
417 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
418 self.inner.read_to_end(buf)
421 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
422 self.inner.read_to_string(buf)
425 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
426 self.inner.read_exact(buf)
430 #[stable(feature = "rust1", since = "1.0.0")]
431 impl BufRead for StdinLock<'_> {
432 fn fill_buf(&mut self) -> io::Result<&[u8]> {
433 self.inner.fill_buf()
436 fn consume(&mut self, n: usize) {
437 self.inner.consume(n)
440 fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
441 self.inner.read_until(byte, buf)
444 fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
445 self.inner.read_line(buf)
449 #[stable(feature = "std_debug", since = "1.16.0")]
450 impl fmt::Debug for StdinLock<'_> {
451 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
452 f.pad("StdinLock { .. }")
456 /// A handle to the global standard output stream of the current process.
458 /// Each handle shares a global buffer of data to be written to the standard
459 /// output stream. Access is also synchronized via a lock and explicit control
460 /// over locking is available via the [`lock`] method.
462 /// Created by the [`io::stdout`] method.
464 /// ### Note: Windows Portability Consideration
465 /// When operating in a console, the Windows implementation of this stream does not support
466 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
469 /// [`lock`]: Stdout::lock
470 /// [`io::stdout`]: stdout
471 #[stable(feature = "rust1", since = "1.0.0")]
473 // FIXME: this should be LineWriter or BufWriter depending on the state of
474 // stdout (tty or not). Note that if this is not line buffered it
475 // should also flush-on-panic or some form of flush-on-abort.
476 inner: Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
479 /// A locked reference to the `Stdout` handle.
481 /// This handle implements the [`Write`] trait, and is constructed via
482 /// the [`Stdout::lock`] method.
484 /// ### Note: Windows Portability Consideration
485 /// When operating in a console, the Windows implementation of this stream does not support
486 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
488 #[stable(feature = "rust1", since = "1.0.0")]
489 pub struct StdoutLock<'a> {
490 inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
493 /// Constructs a new handle to the standard output of the current process.
495 /// Each handle returned is a reference to a shared global buffer whose access
496 /// is synchronized via a mutex. If you need more explicit control over
497 /// locking, see the [`Stdout::lock`] method.
499 /// ### Note: Windows Portability Consideration
500 /// When operating in a console, the Windows implementation of this stream does not support
501 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
506 /// Using implicit synchronization:
509 /// use std::io::{self, Write};
511 /// fn main() -> io::Result<()> {
512 /// io::stdout().write_all(b"hello world")?;
518 /// Using explicit synchronization:
521 /// use std::io::{self, Write};
523 /// fn main() -> io::Result<()> {
524 /// let stdout = io::stdout();
525 /// let mut handle = stdout.lock();
527 /// handle.write_all(b"hello world")?;
532 #[stable(feature = "rust1", since = "1.0.0")]
533 pub fn stdout() -> Stdout {
534 static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = Lazy::new();
536 inner: unsafe { INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown") },
539 fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> {
540 // This must not reentrantly access `INSTANCE`
541 let stdout = stdout_raw();
543 let ret = Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))));
551 /// Locks this handle to the standard output stream, returning a writable
554 /// The lock is released when the returned lock goes out of scope. The
555 /// returned guard also implements the `Write` trait for writing data.
560 /// use std::io::{self, Write};
562 /// fn main() -> io::Result<()> {
563 /// let stdout = io::stdout();
564 /// let mut handle = stdout.lock();
566 /// handle.write_all(b"hello world")?;
571 #[stable(feature = "rust1", since = "1.0.0")]
572 pub fn lock(&self) -> StdoutLock<'_> {
573 StdoutLock { inner: self.inner.lock() }
577 #[stable(feature = "std_debug", since = "1.16.0")]
578 impl fmt::Debug for Stdout {
579 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
580 f.pad("Stdout { .. }")
584 #[stable(feature = "rust1", since = "1.0.0")]
585 impl Write for Stdout {
586 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
587 self.lock().write(buf)
589 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
590 self.lock().write_vectored(bufs)
593 fn is_write_vectored(&self) -> bool {
594 self.lock().is_write_vectored()
596 fn flush(&mut self) -> io::Result<()> {
599 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
600 self.lock().write_all(buf)
602 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
603 self.lock().write_all_vectored(bufs)
605 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
606 self.lock().write_fmt(args)
609 #[stable(feature = "rust1", since = "1.0.0")]
610 impl Write for StdoutLock<'_> {
611 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
612 self.inner.borrow_mut().write(buf)
614 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
615 self.inner.borrow_mut().write_vectored(bufs)
618 fn is_write_vectored(&self) -> bool {
619 self.inner.borrow_mut().is_write_vectored()
621 fn flush(&mut self) -> io::Result<()> {
622 self.inner.borrow_mut().flush()
624 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
625 self.inner.borrow_mut().write_all(buf)
627 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
628 self.inner.borrow_mut().write_all_vectored(bufs)
632 #[stable(feature = "std_debug", since = "1.16.0")]
633 impl fmt::Debug for StdoutLock<'_> {
634 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635 f.pad("StdoutLock { .. }")
639 /// A handle to the standard error stream of a process.
641 /// For more information, see the [`io::stderr`] method.
643 /// [`io::stderr`]: stderr
645 /// ### Note: Windows Portability Consideration
646 /// When operating in a console, the Windows implementation of this stream does not support
647 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
649 #[stable(feature = "rust1", since = "1.0.0")]
651 inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
654 /// A locked reference to the `Stderr` handle.
656 /// This handle implements the `Write` trait and is constructed via
657 /// the [`Stderr::lock`] method.
659 /// ### Note: Windows Portability Consideration
660 /// When operating in a console, the Windows implementation of this stream does not support
661 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
663 #[stable(feature = "rust1", since = "1.0.0")]
664 pub struct StderrLock<'a> {
665 inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
668 /// Constructs a new handle to the standard error of the current process.
670 /// This handle is not buffered.
672 /// ### Note: Windows Portability Consideration
673 /// When operating in a console, the Windows implementation of this stream does not support
674 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
679 /// Using implicit synchronization:
682 /// use std::io::{self, Write};
684 /// fn main() -> io::Result<()> {
685 /// io::stderr().write_all(b"hello world")?;
691 /// Using explicit synchronization:
694 /// use std::io::{self, Write};
696 /// fn main() -> io::Result<()> {
697 /// let stderr = io::stderr();
698 /// let mut handle = stderr.lock();
700 /// handle.write_all(b"hello world")?;
705 #[stable(feature = "rust1", since = "1.0.0")]
706 pub fn stderr() -> Stderr {
707 // Note that unlike `stdout()` we don't use `Lazy` here which registers a
708 // destructor. Stderr is not buffered nor does the `stderr_raw` type consume
709 // any owned resources, so there's no need to run any destructors at some
710 // point in the future.
712 // This has the added benefit of allowing `stderr` to be usable during
713 // process shutdown as well!
714 static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
715 unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) };
717 // When accessing stderr we need one-time initialization of the reentrant
718 // mutex. Afterwards we can just always use the now-filled-in `INSTANCE` value.
719 static INIT: Once = Once::new();
720 INIT.call_once(|| unsafe {
723 Stderr { inner: &INSTANCE }
727 /// Locks this handle to the standard error stream, returning a writable
730 /// The lock is released when the returned lock goes out of scope. The
731 /// returned guard also implements the [`Write`] trait for writing data.
736 /// use std::io::{self, Write};
738 /// fn foo() -> io::Result<()> {
739 /// let stderr = io::stderr();
740 /// let mut handle = stderr.lock();
742 /// handle.write_all(b"hello world")?;
747 #[stable(feature = "rust1", since = "1.0.0")]
748 pub fn lock(&self) -> StderrLock<'_> {
749 StderrLock { inner: self.inner.lock() }
753 #[stable(feature = "std_debug", since = "1.16.0")]
754 impl fmt::Debug for Stderr {
755 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
756 f.pad("Stderr { .. }")
760 #[stable(feature = "rust1", since = "1.0.0")]
761 impl Write for Stderr {
762 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
763 self.lock().write(buf)
765 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
766 self.lock().write_vectored(bufs)
769 fn is_write_vectored(&self) -> bool {
770 self.lock().is_write_vectored()
772 fn flush(&mut self) -> io::Result<()> {
775 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
776 self.lock().write_all(buf)
778 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
779 self.lock().write_all_vectored(bufs)
781 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
782 self.lock().write_fmt(args)
785 #[stable(feature = "rust1", since = "1.0.0")]
786 impl Write for StderrLock<'_> {
787 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
788 self.inner.borrow_mut().write(buf)
790 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
791 self.inner.borrow_mut().write_vectored(bufs)
794 fn is_write_vectored(&self) -> bool {
795 self.inner.borrow_mut().is_write_vectored()
797 fn flush(&mut self) -> io::Result<()> {
798 self.inner.borrow_mut().flush()
800 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
801 self.inner.borrow_mut().write_all(buf)
803 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
804 self.inner.borrow_mut().write_all_vectored(bufs)
808 #[stable(feature = "std_debug", since = "1.16.0")]
809 impl fmt::Debug for StderrLock<'_> {
810 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
811 f.pad("StderrLock { .. }")
815 /// Resets the thread-local stderr handle to the specified writer
817 /// This will replace the current thread's stderr handle, returning the old
818 /// handle. All future calls to `panic!` and friends will emit their output to
819 /// this specified handle.
821 /// Note that this does not need to be called for all new threads; the default
822 /// output handle is to the process's stderr stream.
824 feature = "set_stdio",
825 reason = "this function may disappear completely or be replaced \
826 with a more general mechanism",
830 pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
832 LOCAL_STDERR.with(move |slot| mem::replace(&mut *slot.borrow_mut(), sink)).and_then(|mut s| {
838 /// Resets the thread-local stdout handle to the specified writer
840 /// This will replace the current thread's stdout handle, returning the old
841 /// handle. All future calls to `print!` and friends will emit their output to
842 /// this specified handle.
844 /// Note that this does not need to be called for all new threads; the default
845 /// output handle is to the process's stdout stream.
847 feature = "set_stdio",
848 reason = "this function may disappear completely or be replaced \
849 with a more general mechanism",
853 pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
855 LOCAL_STDOUT.with(move |slot| mem::replace(&mut *slot.borrow_mut(), sink)).and_then(|mut s| {
861 /// Write `args` to output stream `local_s` if possible, `global_s`
862 /// otherwise. `label` identifies the stream in a panic message.
864 /// This function is used to print error messages, so it takes extra
865 /// care to avoid causing a panic when `local_s` is unusable.
866 /// For instance, if the TLS key for the local stream is
867 /// already destroyed, or if the local stream is locked by another
868 /// thread, it will just fall back to the global stream.
870 /// However, if the actual I/O causes an error, this function does panic.
872 args: fmt::Arguments<'_>,
873 local_s: &'static LocalKey<RefCell<Option<Box<dyn Write + Send>>>>,
881 // Note that we completely remove a local sink to write to in case
882 // our printing recursively panics/prints, so the recursive
883 // panic/print goes to the global sink instead of our local sink.
884 let prev = s.borrow_mut().take();
885 if let Some(mut w) = prev {
886 let result = w.write_fmt(args);
887 *s.borrow_mut() = Some(w);
890 global_s().write_fmt(args)
892 .unwrap_or_else(|_| global_s().write_fmt(args));
894 if let Err(e) = result {
895 panic!("failed printing to {}: {}", label, e);
900 feature = "print_internals",
901 reason = "implementation detail which may disappear or be replaced at any time",
906 pub fn _print(args: fmt::Arguments<'_>) {
907 print_to(args, &LOCAL_STDOUT, stdout, "stdout");
911 feature = "print_internals",
912 reason = "implementation detail which may disappear or be replaced at any time",
917 pub fn _eprint(args: fmt::Arguments<'_>) {
918 print_to(args, &LOCAL_STDERR, stderr, "stderr");
922 pub use realstd::io::{_eprint, _print};
927 use crate::panic::{RefUnwindSafe, UnwindSafe};
931 fn stdout_unwind_safe() {
932 assert_unwind_safe::<Stdout>();
935 fn stdoutlock_unwind_safe() {
936 assert_unwind_safe::<StdoutLock<'_>>();
937 assert_unwind_safe::<StdoutLock<'static>>();
940 fn stderr_unwind_safe() {
941 assert_unwind_safe::<Stderr>();
944 fn stderrlock_unwind_safe() {
945 assert_unwind_safe::<StderrLock<'_>>();
946 assert_unwind_safe::<StderrLock<'static>>();
949 fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}
952 #[cfg_attr(target_os = "emscripten", ignore)]
953 fn panic_doesnt_poison() {