Skip to content

Commit 63e67ce

Browse files
authored
Rollup merge of #69959 - alexcrichton:fix-panic-in-print, r=Mark-Simulacrum
std: Don't abort process when printing panics in tests This commit fixes an issue when using `set_print` and friends, notably used by libtest, to avoid aborting the process if printing panics. This previously panicked due to borrowing a mutable `RefCell` twice, and this is worked around by borrowing these cells for less time, instead taking out and removing contents temporarily. Closes #69558
2 parents d6f4e39 + 773c04c commit 63e67ce

File tree

3 files changed

+56
-4
lines changed

3 files changed

+56
-4
lines changed

src/libstd/io/stdio.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -805,10 +805,14 @@ fn print_to<T>(
805805
{
806806
let result = local_s
807807
.try_with(|s| {
808-
if let Ok(mut borrowed) = s.try_borrow_mut() {
809-
if let Some(w) = borrowed.as_mut() {
810-
return w.write_fmt(args);
811-
}
808+
// Note that we completely remove a local sink to write to in case
809+
// our printing recursively panics/prints, so the recursive
810+
// panic/print goes to the global sink instead of our local sink.
811+
let prev = s.borrow_mut().take();
812+
if let Some(mut w) = prev {
813+
let result = w.write_fmt(args);
814+
*s.borrow_mut() = Some(w);
815+
return result;
812816
}
813817
global_s().write_fmt(args)
814818
})

src/test/ui/panic-while-printing.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// run-pass
2+
// ignore-wasm no subprocess support
3+
4+
#![feature(set_stdio)]
5+
6+
use std::fmt;
7+
use std::fmt::{Display, Formatter};
8+
use std::io::set_panic;
9+
10+
pub struct A;
11+
12+
impl Display for A {
13+
fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
14+
panic!();
15+
}
16+
}
17+
18+
fn main() {
19+
set_panic(Some(Box::new(Vec::new())));
20+
assert!(std::panic::catch_unwind(|| {
21+
eprintln!("{}", A);
22+
})
23+
.is_err());
24+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// compile-flags:--test
2+
// run-pass
3+
// ignore-wasm no subprocess support
4+
5+
use std::fmt;
6+
use std::fmt::{Display, Formatter};
7+
8+
pub struct A(Vec<u32>);
9+
10+
impl Display for A {
11+
fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
12+
self.0[0];
13+
Ok(())
14+
}
15+
}
16+
17+
#[test]
18+
fn main() {
19+
let result = std::panic::catch_unwind(|| {
20+
let a = A(vec![]);
21+
eprintln!("{}", a);
22+
});
23+
assert!(result.is_err());
24+
}

0 commit comments

Comments
 (0)