1 use crate::io::blocking::Blocking; 2 use crate::io::stdio_common::SplitByUtf8BoundaryIfWindows; 3 use crate::io::AsyncWrite; 4 5 use std::io; 6 use std::pin::Pin; 7 use std::task::Context; 8 use std::task::Poll; 9 10 cfg_io_std! { 11 /// A handle to the standard error stream of a process. 12 /// 13 /// Concurrent writes to stderr must be executed with care: Only individual 14 /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular 15 /// you should be aware that writes using [`write_all`] are not guaranteed 16 /// to occur as a single write, so multiple threads writing data with 17 /// [`write_all`] may result in interleaved output. 18 /// 19 /// Created by the [`stderr`] function. 20 /// 21 /// [`stderr`]: stderr() 22 /// [`AsyncWrite`]: AsyncWrite 23 /// [`write_all`]: crate::io::AsyncWriteExt::write_all() 24 /// 25 /// # Examples 26 /// 27 /// ``` 28 /// use tokio::io::{self, AsyncWriteExt}; 29 /// 30 /// #[tokio::main] 31 /// async fn main() -> io::Result<()> { 32 /// let mut stderr = io::stdout(); 33 /// stderr.write_all(b"Print some error here.").await?; 34 /// Ok(()) 35 /// } 36 /// ``` 37 #[derive(Debug)] 38 pub struct Stderr { 39 std: SplitByUtf8BoundaryIfWindows<Blocking<std::io::Stderr>>, 40 } 41 42 /// Constructs a new handle to the standard error of the current process. 43 /// 44 /// The returned handle allows writing to standard error from the within the 45 /// Tokio runtime. 46 /// 47 /// Concurrent writes to stderr must be executed with care: Only individual 48 /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular 49 /// you should be aware that writes using [`write_all`] are not guaranteed 50 /// to occur as a single write, so multiple threads writing data with 51 /// [`write_all`] may result in interleaved output. 52 /// 53 /// [`AsyncWrite`]: AsyncWrite 54 /// [`write_all`]: crate::io::AsyncWriteExt::write_all() 55 /// 56 /// # Examples 57 /// 58 /// ``` 59 /// use tokio::io::{self, AsyncWriteExt}; 60 /// 61 /// #[tokio::main] 62 /// async fn main() -> io::Result<()> { 63 /// let mut stderr = io::stderr(); 64 /// stderr.write_all(b"Print some error here.").await?; 65 /// Ok(()) 66 /// } 67 /// ``` 68 pub fn stderr() -> Stderr { 69 let std = io::stderr(); 70 Stderr { 71 std: SplitByUtf8BoundaryIfWindows::new(Blocking::new(std)), 72 } 73 } 74 } 75 76 #[cfg(unix)] 77 mod sys { 78 use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; 79 80 use super::Stderr; 81 82 impl AsRawFd for Stderr { as_raw_fd(&self) -> RawFd83 fn as_raw_fd(&self) -> RawFd { 84 std::io::stderr().as_raw_fd() 85 } 86 } 87 88 impl AsFd for Stderr { as_fd(&self) -> BorrowedFd<'_>89 fn as_fd(&self) -> BorrowedFd<'_> { 90 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } 91 } 92 } 93 } 94 95 cfg_windows! { 96 use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle}; 97 98 impl AsRawHandle for Stderr { 99 fn as_raw_handle(&self) -> RawHandle { 100 std::io::stderr().as_raw_handle() 101 } 102 } 103 104 impl AsHandle for Stderr { 105 fn as_handle(&self) -> BorrowedHandle<'_> { 106 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } 107 } 108 } 109 } 110 111 impl AsyncWrite for Stderr { poll_write( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<io::Result<usize>>112 fn poll_write( 113 mut self: Pin<&mut Self>, 114 cx: &mut Context<'_>, 115 buf: &[u8], 116 ) -> Poll<io::Result<usize>> { 117 Pin::new(&mut self.std).poll_write(cx, buf) 118 } 119 poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>120 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { 121 Pin::new(&mut self.std).poll_flush(cx) 122 } 123 poll_shutdown( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Result<(), io::Error>>124 fn poll_shutdown( 125 mut self: Pin<&mut Self>, 126 cx: &mut Context<'_>, 127 ) -> Poll<Result<(), io::Error>> { 128 Pin::new(&mut self.std).poll_shutdown(cx) 129 } 130 } 131