Skip to content

Commit 94118a4

Browse files
Fix & add panic payload tests.
1. Fix runtime UI test that expected drop of panic payload to unwind 2. Add panic payload tests: ensure proper drop, and add one with catch_unwind 3. Add test asserting proper abort of unwind in panic payload
1 parent 6d7ee4b commit 94118a4

File tree

4 files changed

+134
-6
lines changed

4 files changed

+134
-6
lines changed

Diff for: library/std/src/panic/tests.rs

+30
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,33 @@ fn panic_safety_traits() {
5454
assert::<Arc<AssertUnwindSafe<T>>>();
5555
}
5656
}
57+
58+
#[test]
59+
fn test_try_panic_any_message_drop_glue_does_happen() {
60+
use crate::sync::Arc;
61+
62+
let count = Arc::new(());
63+
let weak = Arc::downgrade(&count);
64+
65+
match super::catch_unwind(|| super::panic_any(count)) {
66+
Ok(()) => panic!("closure did not panic"),
67+
Err(e) if e.is::<Arc<()>>() => {}
68+
Err(_) => panic!("closure did not panic with the expected payload"),
69+
}
70+
assert!(weak.upgrade().is_none());
71+
}
72+
73+
#[test]
74+
fn test_try_panic_resume_unwind_drop_glue_does_happen() {
75+
use crate::sync::Arc;
76+
77+
let count = Arc::new(());
78+
let weak = Arc::downgrade(&count);
79+
80+
match super::catch_unwind(|| super::resume_unwind(Box::new(count))) {
81+
Ok(()) => panic!("closure did not panic"),
82+
Err(e) if e.is::<Arc<()>>() => {}
83+
Err(_) => panic!("closure did not panic with the expected payload"),
84+
}
85+
assert!(weak.upgrade().is_none());
86+
}

Diff for: library/std/src/thread/tests.rs

+28-2
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,13 @@ fn test_try_panic_any_message_owned_str() {
218218

219219
#[test]
220220
fn test_try_panic_any_message_any() {
221+
type T = Box<dyn Any + Send>;
221222
match thread::spawn(move || {
222-
panic_any(Box::new(413u16) as Box<dyn Any + Send>);
223+
panic_any(Box::new(413u16) as T);
223224
})
224225
.join()
225226
{
226227
Err(e) => {
227-
type T = Box<dyn Any + Send>;
228228
assert!(e.is::<T>());
229229
let any = e.downcast::<T>().unwrap();
230230
assert!(any.is::<u16>());
@@ -244,6 +244,32 @@ fn test_try_panic_any_message_unit_struct() {
244244
}
245245
}
246246

247+
#[test]
248+
fn test_try_panic_any_message_drop_glue_does_happen() {
249+
let count = Arc::new(());
250+
let weak = Arc::downgrade(&count);
251+
252+
match thread::spawn(|| panic_any(count)).join() {
253+
Ok(()) => panic!("thread did not panic"),
254+
Err(e) if e.is::<Arc<()>>() => {}
255+
Err(_) => panic!("thread did not panic with the expected payload"),
256+
}
257+
assert!(weak.upgrade().is_none());
258+
}
259+
260+
#[test]
261+
fn test_try_panic_resume_unwind_drop_glue_does_happen() {
262+
let count = Arc::new(());
263+
let weak = Arc::downgrade(&count);
264+
265+
match thread::spawn(|| crate::panic::resume_unwind(Box::new(count))).join() {
266+
Ok(()) => panic!("thread did not panic"),
267+
Err(e) if e.is::<Arc<()>>() => {}
268+
Err(_) => panic!("thread did not panic with the expected payload"),
269+
}
270+
assert!(weak.upgrade().is_none());
271+
}
272+
247273
#[test]
248274
fn test_park_timeout_unpark_before() {
249275
for _ in 0..10 {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// run-pass
2+
// needs-unwind
3+
// ignore-emscripten no processes
4+
// ignore-sgx no processes
5+
// ignore-wasm32-bare no unwinding panic
6+
// ignore-avr no unwinding panic
7+
// ignore-nvptx64 no unwinding panic
8+
9+
use std::{env, ops::Not, panic, process};
10+
11+
fn main() {
12+
match &env::args().collect::<Vec<_>>()[..] {
13+
[just_me] => parent(just_me),
14+
[_me, subprocess] if subprocess == "panic" => subprocess_panic(),
15+
[_me, subprocess] if subprocess == "resume_unwind" => subprocess_resume_unwind(),
16+
_ => unreachable!(),
17+
}
18+
}
19+
20+
fn parent(self_exe: &str) {
21+
// call the subprocess 1: panic with a drop bomb
22+
let status =
23+
process::Command::new(self_exe)
24+
.arg("panic")
25+
.status()
26+
.expect("running the command should have succeeded")
27+
;
28+
assert!(status.success().not(), "`subprocess_panic()` is expected to have aborted");
29+
30+
// call the subprocess 2: resume_unwind with a drop bomb
31+
let status =
32+
process::Command::new(self_exe)
33+
.arg("resume_unwind")
34+
.status()
35+
.expect("running the command should have succeeded")
36+
;
37+
assert!(status.success().not(), "`subprocess_resume_unwind()` is expected to have aborted");
38+
}
39+
40+
fn subprocess_panic() {
41+
let _ = panic::catch_unwind(|| {
42+
struct Bomb;
43+
44+
impl Drop for Bomb {
45+
fn drop(&mut self) {
46+
panic!();
47+
}
48+
}
49+
50+
let panic_payload = panic::catch_unwind(|| panic::panic_any(Bomb)).unwrap_err();
51+
// Calls `Bomb::drop`, which starts unwinding. But since this is a panic payload already,
52+
// the drop glue is amended to abort on unwind. So this ought to abort the process.
53+
drop(panic_payload);
54+
});
55+
}
56+
57+
fn subprocess_resume_unwind() {
58+
use panic::resume_unwind;
59+
let _ = panic::catch_unwind(|| {
60+
struct Bomb;
61+
62+
impl Drop for Bomb {
63+
fn drop(&mut self) {
64+
panic!();
65+
}
66+
}
67+
68+
let panic_payload = panic::catch_unwind(|| resume_unwind(Box::new(Bomb))).unwrap_err();
69+
// Calls `Bomb::drop`, which starts unwinding. But since this is a panic payload already,
70+
// the drop glue is amended to abort on unwind. So this ought to abort the process.
71+
drop(panic_payload);
72+
});
73+
}

Diff for: src/test/ui/runtime/rt-explody-panic-payloads.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ fn main() {
2121
[..] => std::panic::panic_any(Bomb),
2222
}.expect("running the command should have succeeded");
2323
println!("{:#?}", output);
24-
let stderr = std::str::from_utf8(&output.stderr);
25-
assert!(stderr.map(|v| {
26-
v.ends_with("fatal runtime error: drop of the panic payload panicked\n")
27-
}).unwrap_or(false));
24+
let stderr = std::str::from_utf8(&output.stderr).expect("UTF-8 stderr");
25+
// the drop of the panic payload cannot unwind anymore:
26+
assert!(stderr.contains("fatal runtime error: drop of the panic payload panicked"));
2827
}

0 commit comments

Comments
 (0)