]>
Commit | Line | Data |
---|---|---|
c34b1796 AL |
1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
c34b1796 AL |
11 | use io::prelude::*; |
12 | ||
476ff2be | 13 | use cell::RefCell; |
c34b1796 AL |
14 | use fmt; |
15 | use io::lazy::Lazy; | |
16 | use io::{self, BufReader, LineWriter}; | |
17 | use sync::{Arc, Mutex, MutexGuard}; | |
18 | use sys::stdio; | |
9346a6ac | 19 | use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; |
92a42be0 | 20 | use thread::LocalKeyState; |
c34b1796 AL |
21 | |
22 | /// Stdout used by print! and println! macros | |
23 | thread_local! { | |
24 | static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = { | |
25 | RefCell::new(None) | |
26 | } | |
27 | } | |
28 | ||
29 | /// A handle to a raw instance of the standard input stream of this process. | |
30 | /// | |
31 | /// This handle is not synchronized or buffered in any fashion. Constructed via | |
32 | /// the `std::io::stdio::stdin_raw` function. | |
33 | struct StdinRaw(stdio::Stdin); | |
34 | ||
35 | /// A handle to a raw instance of the standard output stream of this process. | |
36 | /// | |
37 | /// This handle is not synchronized or buffered in any fashion. Constructed via | |
38 | /// the `std::io::stdio::stdout_raw` function. | |
39 | struct StdoutRaw(stdio::Stdout); | |
40 | ||
41 | /// A handle to a raw instance of the standard output stream of this process. | |
42 | /// | |
43 | /// This handle is not synchronized or buffered in any fashion. Constructed via | |
44 | /// the `std::io::stdio::stderr_raw` function. | |
45 | struct StderrRaw(stdio::Stderr); | |
46 | ||
9346a6ac | 47 | /// Constructs a new raw handle to the standard input of this process. |
c34b1796 AL |
48 | /// |
49 | /// The returned handle does not interact with any other handles created nor | |
50 | /// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin` | |
51 | /// handles is **not** available to raw handles returned from this function. | |
52 | /// | |
53 | /// The returned handle has no external synchronization or buffering. | |
62682a34 | 54 | fn stdin_raw() -> io::Result<StdinRaw> { stdio::Stdin::new().map(StdinRaw) } |
c34b1796 | 55 | |
e9174d1e | 56 | /// Constructs a new raw handle to the standard output stream of this process. |
c34b1796 AL |
57 | /// |
58 | /// The returned handle does not interact with any other handles created nor | |
59 | /// handles returned by `std::io::stdout`. Note that data is buffered by the | |
e9174d1e | 60 | /// `std::io::stdout` handles so writes which happen via this raw handle may |
c34b1796 AL |
61 | /// appear before previous writes. |
62 | /// | |
63 | /// The returned handle has no external synchronization or buffering layered on | |
64 | /// top. | |
62682a34 | 65 | fn stdout_raw() -> io::Result<StdoutRaw> { stdio::Stdout::new().map(StdoutRaw) } |
c34b1796 | 66 | |
e9174d1e | 67 | /// Constructs a new raw handle to the standard error stream of this process. |
c34b1796 AL |
68 | /// |
69 | /// The returned handle does not interact with any other handles created nor | |
e9174d1e | 70 | /// handles returned by `std::io::stderr`. |
c34b1796 AL |
71 | /// |
72 | /// The returned handle has no external synchronization or buffering layered on | |
73 | /// top. | |
62682a34 | 74 | fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) } |
c34b1796 AL |
75 | |
76 | impl Read for StdinRaw { | |
77 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } | |
54a0048b SL |
78 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { |
79 | self.0.read_to_end(buf) | |
80 | } | |
c34b1796 AL |
81 | } |
82 | impl Write for StdoutRaw { | |
83 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } | |
476ff2be | 84 | fn flush(&mut self) -> io::Result<()> { self.0.flush() } |
c34b1796 AL |
85 | } |
86 | impl Write for StderrRaw { | |
87 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } | |
476ff2be | 88 | fn flush(&mut self) -> io::Result<()> { self.0.flush() } |
c34b1796 AL |
89 | } |
90 | ||
62682a34 SL |
91 | enum Maybe<T> { |
92 | Real(T), | |
93 | Fake, | |
94 | } | |
95 | ||
96 | impl<W: io::Write> io::Write for Maybe<W> { | |
97 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
98 | match *self { | |
99 | Maybe::Real(ref mut w) => handle_ebadf(w.write(buf), buf.len()), | |
100 | Maybe::Fake => Ok(buf.len()) | |
101 | } | |
102 | } | |
103 | ||
104 | fn flush(&mut self) -> io::Result<()> { | |
105 | match *self { | |
106 | Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()), | |
107 | Maybe::Fake => Ok(()) | |
108 | } | |
109 | } | |
110 | } | |
111 | ||
112 | impl<R: io::Read> io::Read for Maybe<R> { | |
113 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
114 | match *self { | |
7453a54e | 115 | Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), 0), |
62682a34 SL |
116 | Maybe::Fake => Ok(0) |
117 | } | |
118 | } | |
54a0048b SL |
119 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { |
120 | match *self { | |
121 | Maybe::Real(ref mut r) => handle_ebadf(r.read_to_end(buf), 0), | |
122 | Maybe::Fake => Ok(0) | |
123 | } | |
124 | } | |
62682a34 SL |
125 | } |
126 | ||
127 | fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> { | |
c30ab7b3 | 128 | use sys::stdio::EBADF_ERR; |
62682a34 SL |
129 | |
130 | match r { | |
c30ab7b3 | 131 | Err(ref e) if e.raw_os_error() == Some(EBADF_ERR) => Ok(default), |
62682a34 SL |
132 | r => r |
133 | } | |
134 | } | |
135 | ||
c34b1796 AL |
136 | /// A handle to the standard input stream of a process. |
137 | /// | |
138 | /// Each handle is a shared reference to a global buffer of input data to this | |
9cc50fc6 | 139 | /// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods |
54a0048b SL |
140 | /// (e.g. `.lines()`). Reads to this handle are otherwise locked with respect |
141 | /// to other reads. | |
c34b1796 AL |
142 | /// |
143 | /// This handle implements the `Read` trait, but beware that concurrent reads | |
144 | /// of `Stdin` must be executed with care. | |
bd371182 | 145 | /// |
9cc50fc6 SL |
146 | /// Created by the [`io::stdin`] method. |
147 | /// | |
148 | /// [`io::stdin`]: fn.stdin.html | |
149 | /// [`BufRead`]: trait.BufRead.html | |
c34b1796 AL |
150 | #[stable(feature = "rust1", since = "1.0.0")] |
151 | pub struct Stdin { | |
62682a34 | 152 | inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>, |
c34b1796 AL |
153 | } |
154 | ||
b039eaaf | 155 | /// A locked reference to the `Stdin` handle. |
c34b1796 | 156 | /// |
9cc50fc6 SL |
157 | /// This handle implements both the [`Read`] and [`BufRead`] traits, and |
158 | /// is constructed via the [`Stdin::lock`] method. | |
159 | /// | |
160 | /// [`Read`]: trait.Read.html | |
161 | /// [`BufRead`]: trait.BufRead.html | |
162 | /// [`Stdin::lock`]: struct.Stdin.html#method.lock | |
c34b1796 AL |
163 | #[stable(feature = "rust1", since = "1.0.0")] |
164 | pub struct StdinLock<'a> { | |
62682a34 | 165 | inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>, |
c34b1796 AL |
166 | } |
167 | ||
c1a9b12d | 168 | /// Constructs a new handle to the standard input of the current process. |
c34b1796 | 169 | /// |
c1a9b12d SL |
170 | /// Each handle returned is a reference to a shared global buffer whose access |
171 | /// is synchronized via a mutex. If you need more explicit control over | |
9cc50fc6 | 172 | /// locking, see the [`lock() method`][lock]. |
c1a9b12d SL |
173 | /// |
174 | /// [lock]: struct.Stdin.html#method.lock | |
175 | /// | |
176 | /// # Examples | |
177 | /// | |
178 | /// Using implicit synchronization: | |
179 | /// | |
180 | /// ``` | |
181 | /// use std::io::{self, Read}; | |
182 | /// | |
183 | /// # fn foo() -> io::Result<String> { | |
184 | /// let mut buffer = String::new(); | |
32a655c1 | 185 | /// io::stdin().read_to_string(&mut buffer)?; |
c1a9b12d SL |
186 | /// # Ok(buffer) |
187 | /// # } | |
188 | /// ``` | |
189 | /// | |
190 | /// Using explicit synchronization: | |
191 | /// | |
192 | /// ``` | |
193 | /// use std::io::{self, Read}; | |
194 | /// | |
195 | /// # fn foo() -> io::Result<String> { | |
196 | /// let mut buffer = String::new(); | |
197 | /// let stdin = io::stdin(); | |
198 | /// let mut handle = stdin.lock(); | |
c34b1796 | 199 | /// |
32a655c1 | 200 | /// handle.read_to_string(&mut buffer)?; |
c1a9b12d SL |
201 | /// # Ok(buffer) |
202 | /// # } | |
203 | /// ``` | |
c34b1796 AL |
204 | #[stable(feature = "rust1", since = "1.0.0")] |
205 | pub fn stdin() -> Stdin { | |
62682a34 | 206 | static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new(stdin_init); |
c34b1796 AL |
207 | return Stdin { |
208 | inner: INSTANCE.get().expect("cannot access stdin during shutdown"), | |
209 | }; | |
210 | ||
62682a34 SL |
211 | fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> { |
212 | let stdin = match stdin_raw() { | |
213 | Ok(stdin) => Maybe::Real(stdin), | |
214 | _ => Maybe::Fake | |
215 | }; | |
216 | ||
c30ab7b3 | 217 | Arc::new(Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin))) |
c34b1796 AL |
218 | } |
219 | } | |
220 | ||
221 | impl Stdin { | |
9346a6ac | 222 | /// Locks this handle to the standard input stream, returning a readable |
c34b1796 AL |
223 | /// guard. |
224 | /// | |
225 | /// The lock is released when the returned lock goes out of scope. The | |
9cc50fc6 | 226 | /// returned guard also implements the [`Read`] and [`BufRead`] traits for |
c34b1796 | 227 | /// accessing the underlying data. |
9cc50fc6 SL |
228 | /// |
229 | /// [`Read`]: trait.Read.html | |
230 | /// [`BufRead`]: trait.BufRead.html | |
5bcae85e SL |
231 | /// |
232 | /// # Examples | |
233 | /// | |
234 | /// ``` | |
235 | /// use std::io::{self, Read}; | |
236 | /// | |
237 | /// # fn foo() -> io::Result<String> { | |
238 | /// let mut buffer = String::new(); | |
239 | /// let stdin = io::stdin(); | |
240 | /// let mut handle = stdin.lock(); | |
241 | /// | |
32a655c1 | 242 | /// handle.read_to_string(&mut buffer)?; |
5bcae85e SL |
243 | /// # Ok(buffer) |
244 | /// # } | |
245 | /// ``` | |
c34b1796 AL |
246 | #[stable(feature = "rust1", since = "1.0.0")] |
247 | pub fn lock(&self) -> StdinLock { | |
248 | StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } | |
249 | } | |
250 | ||
251 | /// Locks this handle and reads a line of input into the specified buffer. | |
252 | /// | |
253 | /// For detailed semantics of this method, see the documentation on | |
9cc50fc6 SL |
254 | /// [`BufRead::read_line`]. |
255 | /// | |
256 | /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line | |
c1a9b12d SL |
257 | /// |
258 | /// # Examples | |
259 | /// | |
260 | /// ```no_run | |
261 | /// use std::io; | |
262 | /// | |
263 | /// let mut input = String::new(); | |
264 | /// match io::stdin().read_line(&mut input) { | |
265 | /// Ok(n) => { | |
266 | /// println!("{} bytes read", n); | |
267 | /// println!("{}", input); | |
268 | /// } | |
269 | /// Err(error) => println!("error: {}", error), | |
270 | /// } | |
271 | /// ``` | |
272 | /// | |
273 | /// You can run the example one of two ways: | |
274 | /// | |
275 | /// - Pipe some text to it, e.g. `printf foo | path/to/executable` | |
276 | /// - Give it text interactively by running the executable directly, | |
9cc50fc6 | 277 | /// in which case it will wait for the Enter key to be pressed before |
c1a9b12d | 278 | /// continuing |
c34b1796 | 279 | #[stable(feature = "rust1", since = "1.0.0")] |
c1a9b12d | 280 | pub fn read_line(&self, buf: &mut String) -> io::Result<usize> { |
c34b1796 AL |
281 | self.lock().read_line(buf) |
282 | } | |
283 | } | |
284 | ||
8bb4bdeb | 285 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 SL |
286 | impl fmt::Debug for Stdin { |
287 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
288 | f.pad("Stdin { .. }") | |
289 | } | |
290 | } | |
291 | ||
c34b1796 AL |
292 | #[stable(feature = "rust1", since = "1.0.0")] |
293 | impl Read for Stdin { | |
294 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
295 | self.lock().read(buf) | |
296 | } | |
297 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { | |
298 | self.lock().read_to_end(buf) | |
299 | } | |
300 | fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { | |
301 | self.lock().read_to_string(buf) | |
302 | } | |
e9174d1e SL |
303 | fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { |
304 | self.lock().read_exact(buf) | |
305 | } | |
c34b1796 AL |
306 | } |
307 | ||
308 | #[stable(feature = "rust1", since = "1.0.0")] | |
309 | impl<'a> Read for StdinLock<'a> { | |
310 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
311 | self.inner.read(buf) | |
312 | } | |
c1a9b12d | 313 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { |
54a0048b | 314 | self.inner.read_to_end(buf) |
c1a9b12d | 315 | } |
c34b1796 | 316 | } |
62682a34 | 317 | |
c34b1796 AL |
318 | #[stable(feature = "rust1", since = "1.0.0")] |
319 | impl<'a> BufRead for StdinLock<'a> { | |
320 | fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() } | |
321 | fn consume(&mut self, n: usize) { self.inner.consume(n) } | |
322 | } | |
323 | ||
8bb4bdeb | 324 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 SL |
325 | impl<'a> fmt::Debug for StdinLock<'a> { |
326 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
327 | f.pad("StdinLock { .. }") | |
328 | } | |
329 | } | |
330 | ||
c34b1796 AL |
331 | /// A handle to the global standard output stream of the current process. |
332 | /// | |
333 | /// Each handle shares a global buffer of data to be written to the standard | |
334 | /// output stream. Access is also synchronized via a lock and explicit control | |
cc61c64b | 335 | /// over locking is available via the [`lock`] method. |
bd371182 | 336 | /// |
9cc50fc6 SL |
337 | /// Created by the [`io::stdout`] method. |
338 | /// | |
cc61c64b | 339 | /// [`lock`]: #method.lock |
9cc50fc6 | 340 | /// [`io::stdout`]: fn.stdout.html |
c34b1796 AL |
341 | #[stable(feature = "rust1", since = "1.0.0")] |
342 | pub struct Stdout { | |
343 | // FIXME: this should be LineWriter or BufWriter depending on the state of | |
344 | // stdout (tty or not). Note that if this is not line buffered it | |
345 | // should also flush-on-panic or some form of flush-on-abort. | |
62682a34 | 346 | inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>, |
c34b1796 AL |
347 | } |
348 | ||
b039eaaf | 349 | /// A locked reference to the `Stdout` handle. |
c34b1796 | 350 | /// |
9cc50fc6 SL |
351 | /// This handle implements the [`Write`] trait, and is constructed via |
352 | /// the [`Stdout::lock`] method. | |
353 | /// | |
354 | /// [`Write`]: trait.Write.html | |
355 | /// [`Stdout::lock`]: struct.Stdout.html#method.lock | |
c34b1796 AL |
356 | #[stable(feature = "rust1", since = "1.0.0")] |
357 | pub struct StdoutLock<'a> { | |
62682a34 | 358 | inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>, |
c34b1796 AL |
359 | } |
360 | ||
c1a9b12d | 361 | /// Constructs a new handle to the standard output of the current process. |
c34b1796 AL |
362 | /// |
363 | /// Each handle returned is a reference to a shared global buffer whose access | |
c1a9b12d | 364 | /// is synchronized via a mutex. If you need more explicit control over |
9cc50fc6 | 365 | /// locking, see the [Stdout::lock] method. |
c1a9b12d | 366 | /// |
9cc50fc6 | 367 | /// [Stdout::lock]: struct.Stdout.html#method.lock |
c1a9b12d SL |
368 | /// |
369 | /// # Examples | |
c34b1796 | 370 | /// |
c1a9b12d SL |
371 | /// Using implicit synchronization: |
372 | /// | |
373 | /// ``` | |
374 | /// use std::io::{self, Write}; | |
375 | /// | |
376 | /// # fn foo() -> io::Result<()> { | |
32a655c1 | 377 | /// io::stdout().write(b"hello world")?; |
c1a9b12d SL |
378 | /// |
379 | /// # Ok(()) | |
380 | /// # } | |
381 | /// ``` | |
382 | /// | |
383 | /// Using explicit synchronization: | |
384 | /// | |
385 | /// ``` | |
386 | /// use std::io::{self, Write}; | |
387 | /// | |
388 | /// # fn foo() -> io::Result<()> { | |
389 | /// let stdout = io::stdout(); | |
390 | /// let mut handle = stdout.lock(); | |
391 | /// | |
32a655c1 | 392 | /// handle.write(b"hello world")?; |
c1a9b12d SL |
393 | /// |
394 | /// # Ok(()) | |
395 | /// # } | |
396 | /// ``` | |
c34b1796 AL |
397 | #[stable(feature = "rust1", since = "1.0.0")] |
398 | pub fn stdout() -> Stdout { | |
62682a34 SL |
399 | static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> |
400 | = Lazy::new(stdout_init); | |
c34b1796 AL |
401 | return Stdout { |
402 | inner: INSTANCE.get().expect("cannot access stdout during shutdown"), | |
403 | }; | |
404 | ||
62682a34 SL |
405 | fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> { |
406 | let stdout = match stdout_raw() { | |
407 | Ok(stdout) => Maybe::Real(stdout), | |
408 | _ => Maybe::Fake, | |
409 | }; | |
410 | Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout)))) | |
c34b1796 AL |
411 | } |
412 | } | |
413 | ||
414 | impl Stdout { | |
9346a6ac | 415 | /// Locks this handle to the standard output stream, returning a writable |
c34b1796 AL |
416 | /// guard. |
417 | /// | |
418 | /// The lock is released when the returned lock goes out of scope. The | |
419 | /// returned guard also implements the `Write` trait for writing data. | |
5bcae85e SL |
420 | /// |
421 | /// # Examples | |
422 | /// | |
423 | /// ``` | |
424 | /// use std::io::{self, Write}; | |
425 | /// | |
426 | /// # fn foo() -> io::Result<()> { | |
427 | /// let stdout = io::stdout(); | |
428 | /// let mut handle = stdout.lock(); | |
429 | /// | |
32a655c1 | 430 | /// handle.write(b"hello world")?; |
5bcae85e SL |
431 | /// |
432 | /// # Ok(()) | |
433 | /// # } | |
434 | /// ``` | |
c34b1796 AL |
435 | #[stable(feature = "rust1", since = "1.0.0")] |
436 | pub fn lock(&self) -> StdoutLock { | |
437 | StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } | |
438 | } | |
439 | } | |
440 | ||
8bb4bdeb | 441 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 SL |
442 | impl fmt::Debug for Stdout { |
443 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
444 | f.pad("Stdout { .. }") | |
445 | } | |
446 | } | |
447 | ||
c34b1796 AL |
448 | #[stable(feature = "rust1", since = "1.0.0")] |
449 | impl Write for Stdout { | |
450 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
451 | self.lock().write(buf) | |
452 | } | |
453 | fn flush(&mut self) -> io::Result<()> { | |
454 | self.lock().flush() | |
455 | } | |
456 | fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { | |
457 | self.lock().write_all(buf) | |
458 | } | |
9346a6ac AL |
459 | fn write_fmt(&mut self, args: fmt::Arguments) -> io::Result<()> { |
460 | self.lock().write_fmt(args) | |
461 | } | |
c34b1796 AL |
462 | } |
463 | #[stable(feature = "rust1", since = "1.0.0")] | |
464 | impl<'a> Write for StdoutLock<'a> { | |
465 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
54a0048b | 466 | self.inner.borrow_mut().write(buf) |
9346a6ac AL |
467 | } |
468 | fn flush(&mut self) -> io::Result<()> { | |
469 | self.inner.borrow_mut().flush() | |
c34b1796 | 470 | } |
c34b1796 AL |
471 | } |
472 | ||
8bb4bdeb | 473 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 SL |
474 | impl<'a> fmt::Debug for StdoutLock<'a> { |
475 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
476 | f.pad("StdoutLock { .. }") | |
477 | } | |
478 | } | |
479 | ||
c34b1796 AL |
480 | /// A handle to the standard error stream of a process. |
481 | /// | |
9cc50fc6 SL |
482 | /// For more information, see the [`io::stderr`] method. |
483 | /// | |
484 | /// [`io::stderr`]: fn.stderr.html | |
c34b1796 AL |
485 | #[stable(feature = "rust1", since = "1.0.0")] |
486 | pub struct Stderr { | |
62682a34 | 487 | inner: Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>>, |
c34b1796 AL |
488 | } |
489 | ||
b039eaaf | 490 | /// A locked reference to the `Stderr` handle. |
c34b1796 | 491 | /// |
9cc50fc6 SL |
492 | /// This handle implements the `Write` trait and is constructed via |
493 | /// the [`Stderr::lock`] method. | |
494 | /// | |
495 | /// [`Stderr::lock`]: struct.Stderr.html#method.lock | |
c34b1796 AL |
496 | #[stable(feature = "rust1", since = "1.0.0")] |
497 | pub struct StderrLock<'a> { | |
62682a34 | 498 | inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>, |
c34b1796 AL |
499 | } |
500 | ||
c1a9b12d SL |
501 | /// Constructs a new handle to the standard error of the current process. |
502 | /// | |
503 | /// This handle is not buffered. | |
504 | /// | |
505 | /// # Examples | |
506 | /// | |
507 | /// Using implicit synchronization: | |
508 | /// | |
509 | /// ``` | |
510 | /// use std::io::{self, Write}; | |
511 | /// | |
512 | /// # fn foo() -> io::Result<()> { | |
32a655c1 | 513 | /// io::stderr().write(b"hello world")?; |
c1a9b12d SL |
514 | /// |
515 | /// # Ok(()) | |
516 | /// # } | |
517 | /// ``` | |
518 | /// | |
519 | /// Using explicit synchronization: | |
520 | /// | |
521 | /// ``` | |
522 | /// use std::io::{self, Write}; | |
523 | /// | |
524 | /// # fn foo() -> io::Result<()> { | |
525 | /// let stderr = io::stderr(); | |
526 | /// let mut handle = stderr.lock(); | |
c34b1796 | 527 | /// |
32a655c1 | 528 | /// handle.write(b"hello world")?; |
c34b1796 | 529 | /// |
c1a9b12d SL |
530 | /// # Ok(()) |
531 | /// # } | |
532 | /// ``` | |
c34b1796 AL |
533 | #[stable(feature = "rust1", since = "1.0.0")] |
534 | pub fn stderr() -> Stderr { | |
62682a34 | 535 | static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new(stderr_init); |
c34b1796 AL |
536 | return Stderr { |
537 | inner: INSTANCE.get().expect("cannot access stderr during shutdown"), | |
538 | }; | |
539 | ||
62682a34 SL |
540 | fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> { |
541 | let stderr = match stderr_raw() { | |
542 | Ok(stderr) => Maybe::Real(stderr), | |
543 | _ => Maybe::Fake, | |
544 | }; | |
545 | Arc::new(ReentrantMutex::new(RefCell::new(stderr))) | |
c34b1796 AL |
546 | } |
547 | } | |
548 | ||
549 | impl Stderr { | |
9346a6ac | 550 | /// Locks this handle to the standard error stream, returning a writable |
c34b1796 AL |
551 | /// guard. |
552 | /// | |
553 | /// The lock is released when the returned lock goes out of scope. The | |
554 | /// returned guard also implements the `Write` trait for writing data. | |
5bcae85e SL |
555 | /// |
556 | /// # Examples | |
557 | /// | |
558 | /// ``` | |
559 | /// use std::io::{self, Write}; | |
560 | /// | |
561 | /// fn foo() -> io::Result<()> { | |
562 | /// let stderr = io::stderr(); | |
563 | /// let mut handle = stderr.lock(); | |
564 | /// | |
32a655c1 | 565 | /// handle.write(b"hello world")?; |
5bcae85e SL |
566 | /// |
567 | /// Ok(()) | |
568 | /// } | |
569 | /// ``` | |
c34b1796 AL |
570 | #[stable(feature = "rust1", since = "1.0.0")] |
571 | pub fn lock(&self) -> StderrLock { | |
572 | StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } | |
573 | } | |
574 | } | |
575 | ||
8bb4bdeb | 576 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 SL |
577 | impl fmt::Debug for Stderr { |
578 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
579 | f.pad("Stderr { .. }") | |
580 | } | |
581 | } | |
582 | ||
c34b1796 AL |
583 | #[stable(feature = "rust1", since = "1.0.0")] |
584 | impl Write for Stderr { | |
585 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
586 | self.lock().write(buf) | |
587 | } | |
588 | fn flush(&mut self) -> io::Result<()> { | |
589 | self.lock().flush() | |
590 | } | |
591 | fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { | |
592 | self.lock().write_all(buf) | |
593 | } | |
9346a6ac AL |
594 | fn write_fmt(&mut self, args: fmt::Arguments) -> io::Result<()> { |
595 | self.lock().write_fmt(args) | |
596 | } | |
c34b1796 AL |
597 | } |
598 | #[stable(feature = "rust1", since = "1.0.0")] | |
599 | impl<'a> Write for StderrLock<'a> { | |
600 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
54a0048b | 601 | self.inner.borrow_mut().write(buf) |
9346a6ac AL |
602 | } |
603 | fn flush(&mut self) -> io::Result<()> { | |
604 | self.inner.borrow_mut().flush() | |
c34b1796 | 605 | } |
c34b1796 AL |
606 | } |
607 | ||
8bb4bdeb | 608 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 SL |
609 | impl<'a> fmt::Debug for StderrLock<'a> { |
610 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
611 | f.pad("StderrLock { .. }") | |
612 | } | |
613 | } | |
614 | ||
bd371182 | 615 | /// Resets the thread-local stderr handle to the specified writer |
c34b1796 | 616 | /// |
bd371182 | 617 | /// This will replace the current thread's stderr handle, returning the old |
c34b1796 AL |
618 | /// handle. All future calls to `panic!` and friends will emit their output to |
619 | /// this specified handle. | |
620 | /// | |
bd371182 | 621 | /// Note that this does not need to be called for all new threads; the default |
c34b1796 AL |
622 | /// output handle is to the process's stderr stream. |
623 | #[unstable(feature = "set_stdio", | |
624 | reason = "this function may disappear completely or be replaced \ | |
e9174d1e SL |
625 | with a more general mechanism", |
626 | issue = "0")] | |
c34b1796 | 627 | #[doc(hidden)] |
c30ab7b3 | 628 | pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { |
c34b1796 AL |
629 | use panicking::LOCAL_STDERR; |
630 | use mem; | |
631 | LOCAL_STDERR.with(move |slot| { | |
c30ab7b3 | 632 | mem::replace(&mut *slot.borrow_mut(), sink) |
c34b1796 AL |
633 | }).and_then(|mut s| { |
634 | let _ = s.flush(); | |
635 | Some(s) | |
636 | }) | |
637 | } | |
638 | ||
bd371182 | 639 | /// Resets the thread-local stdout handle to the specified writer |
c34b1796 | 640 | /// |
bd371182 | 641 | /// This will replace the current thread's stdout handle, returning the old |
c34b1796 AL |
642 | /// handle. All future calls to `print!` and friends will emit their output to |
643 | /// this specified handle. | |
644 | /// | |
bd371182 | 645 | /// Note that this does not need to be called for all new threads; the default |
c34b1796 AL |
646 | /// output handle is to the process's stdout stream. |
647 | #[unstable(feature = "set_stdio", | |
648 | reason = "this function may disappear completely or be replaced \ | |
e9174d1e SL |
649 | with a more general mechanism", |
650 | issue = "0")] | |
c34b1796 | 651 | #[doc(hidden)] |
c30ab7b3 | 652 | pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { |
c34b1796 AL |
653 | use mem; |
654 | LOCAL_STDOUT.with(move |slot| { | |
c30ab7b3 | 655 | mem::replace(&mut *slot.borrow_mut(), sink) |
c34b1796 AL |
656 | }).and_then(|mut s| { |
657 | let _ = s.flush(); | |
658 | Some(s) | |
659 | }) | |
660 | } | |
661 | ||
662 | #[unstable(feature = "print", | |
e9174d1e SL |
663 | reason = "implementation detail which may disappear or be replaced at any time", |
664 | issue = "0")] | |
c34b1796 AL |
665 | #[doc(hidden)] |
666 | pub fn _print(args: fmt::Arguments) { | |
92a42be0 SL |
667 | // As an implementation of the `println!` macro, we want to try our best to |
668 | // not panic wherever possible and get the output somewhere. There are | |
669 | // currently two possible vectors for panics we take care of here: | |
670 | // | |
671 | // 1. If the TLS key for the local stdout has been destroyed, accessing it | |
672 | // would cause a panic. Note that we just lump in the uninitialized case | |
673 | // here for convenience, we're not trying to avoid a panic. | |
674 | // 2. If the local stdout is currently in use (e.g. we're in the middle of | |
675 | // already printing) then accessing again would cause a panic. | |
676 | // | |
677 | // If, however, the actual I/O causes an error, we do indeed panic. | |
678 | let result = match LOCAL_STDOUT.state() { | |
679 | LocalKeyState::Uninitialized | | |
680 | LocalKeyState::Destroyed => stdout().write_fmt(args), | |
681 | LocalKeyState::Valid => { | |
682 | LOCAL_STDOUT.with(|s| { | |
476ff2be SL |
683 | if let Ok(mut borrowed) = s.try_borrow_mut() { |
684 | if let Some(w) = borrowed.as_mut() { | |
92a42be0 SL |
685 | return w.write_fmt(args); |
686 | } | |
687 | } | |
688 | stdout().write_fmt(args) | |
689 | }) | |
c34b1796 | 690 | } |
92a42be0 | 691 | }; |
c34b1796 AL |
692 | if let Err(e) = result { |
693 | panic!("failed printing to stdout: {}", e); | |
694 | } | |
695 | } | |
696 | ||
697 | #[cfg(test)] | |
d9579d0f | 698 | mod tests { |
c34b1796 AL |
699 | use thread; |
700 | use super::*; | |
701 | ||
702 | #[test] | |
c30ab7b3 | 703 | #[cfg_attr(target_os = "emscripten", ignore)] |
c34b1796 AL |
704 | fn panic_doesnt_poison() { |
705 | thread::spawn(|| { | |
706 | let _a = stdin(); | |
707 | let _a = _a.lock(); | |
708 | let _a = stdout(); | |
709 | let _a = _a.lock(); | |
710 | let _a = stderr(); | |
711 | let _a = _a.lock(); | |
712 | panic!(); | |
713 | }).join().unwrap_err(); | |
714 | ||
715 | let _a = stdin(); | |
716 | let _a = _a.lock(); | |
717 | let _a = stdout(); | |
718 | let _a = _a.lock(); | |
719 | let _a = stderr(); | |
720 | let _a = _a.lock(); | |
721 | } | |
722 | } |