|
11 | 11 | use prelude::v1::*;
|
12 | 12 | use io::prelude::*;
|
13 | 13 |
|
14 |
| -use cell::RefCell; |
| 14 | +use cell::{RefCell, BorrowState}; |
15 | 15 | use cmp;
|
16 | 16 | use fmt;
|
17 | 17 | use io::lazy::Lazy;
|
@@ -264,9 +264,8 @@ impl Write for Stdout {
|
264 | 264 | fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
265 | 265 | self.lock().write_all(buf)
|
266 | 266 | }
|
267 |
| - fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { |
268 |
| - self.lock().write_fmt(fmt) |
269 |
| - } |
| 267 | + // Don't override write_fmt as it's possible to run arbitrary code during a |
| 268 | + // write_fmt, allowing the possibility of a recursive lock (aka deadlock) |
270 | 269 | }
|
271 | 270 | #[stable(feature = "rust1", since = "1.0.0")]
|
272 | 271 | impl<'a> Write for StdoutLock<'a> {
|
@@ -334,9 +333,7 @@ impl Write for Stderr {
|
334 | 333 | fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
335 | 334 | self.lock().write_all(buf)
|
336 | 335 | }
|
337 |
| - fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { |
338 |
| - self.lock().write_fmt(fmt) |
339 |
| - } |
| 336 | + // Don't override write_fmt for the same reasons as Stdout |
340 | 337 | }
|
341 | 338 | #[stable(feature = "rust1", since = "1.0.0")]
|
342 | 339 | impl<'a> Write for StderrLock<'a> {
|
@@ -395,10 +392,15 @@ pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
|
395 | 392 | reason = "implementation detail which may disappear or be replaced at any time")]
|
396 | 393 | #[doc(hidden)]
|
397 | 394 | pub fn _print(args: fmt::Arguments) {
|
398 |
| - if let Err(e) = LOCAL_STDOUT.with(|s| match s.borrow_mut().as_mut() { |
399 |
| - Some(w) => w.write_fmt(args), |
400 |
| - None => stdout().write_fmt(args) |
401 |
| - }) { |
| 395 | + let result = LOCAL_STDOUT.with(|s| { |
| 396 | + if s.borrow_state() == BorrowState::Unused { |
| 397 | + if let Some(w) = s.borrow_mut().as_mut() { |
| 398 | + return w.write_fmt(args); |
| 399 | + } |
| 400 | + } |
| 401 | + stdout().write_fmt(args) |
| 402 | + }); |
| 403 | + if let Err(e) = result { |
402 | 404 | panic!("failed printing to stdout: {}", e);
|
403 | 405 | }
|
404 | 406 | }
|
|
0 commit comments