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 impl std::os::unix::io::AsRawFd for Stderr { as_raw_fd(&self) -> std::os::unix::io::RawFd78 fn as_raw_fd(&self) -> std::os::unix::io::RawFd { 79 std::io::stderr().as_raw_fd() 80 } 81 } 82 83 #[cfg(windows)] 84 impl std::os::windows::io::AsRawHandle for Stderr { as_raw_handle(&self) -> std::os::windows::io::RawHandle85 fn as_raw_handle(&self) -> std::os::windows::io::RawHandle { 86 std::io::stderr().as_raw_handle() 87 } 88 } 89 90 impl AsyncWrite for Stderr { poll_write( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<io::Result<usize>>91 fn poll_write( 92 mut self: Pin<&mut Self>, 93 cx: &mut Context<'_>, 94 buf: &[u8], 95 ) -> Poll<io::Result<usize>> { 96 Pin::new(&mut self.std).poll_write(cx, buf) 97 } 98 poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>99 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { 100 Pin::new(&mut self.std).poll_flush(cx) 101 } 102 poll_shutdown( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Result<(), io::Error>>103 fn poll_shutdown( 104 mut self: Pin<&mut Self>, 105 cx: &mut Context<'_>, 106 ) -> Poll<Result<(), io::Error>> { 107 Pin::new(&mut self.std).poll_shutdown(cx) 108 } 109 } 110