@@ -22,6 +22,26 @@ extern "C" fn panic_in_ffi() {
2222 panic ! ( "Test" ) ;
2323}
2424
25+ #[ unwind( allowed) ]
26+ unsafe extern "C" fn unsafe_panic_allow_in_ffi ( ) {
27+ panic ! ( "Test" ) ;
28+ }
29+
30+ #[ unwind( aborts) ]
31+ unsafe extern "C" fn unsafe_abort_in_ffi ( ) {
32+ panic ! ( "Test" ) ;
33+ }
34+
35+ #[ unwind( allowed) ]
36+ extern "C" fn nopanic_in_ffi ( ) {
37+ panic ! ( "Test" ) ;
38+ }
39+
40+ #[ unwind( aborts) ]
41+ extern "C" fn abort_in_ffi ( ) {
42+ panic ! ( "Test" ) ;
43+ }
44+
2545fn test ( ) {
2646 // A safe extern "C" function that panics should abort the process:
2747 let _ = panic:: catch_unwind ( || panic_in_ffi ( ) ) ;
@@ -31,10 +51,36 @@ fn test() {
3151 let _ = io:: stdout ( ) . flush ( ) ;
3252}
3353
54+ fn test2 ( ) {
55+ // A safe extern "C" function that panics should abort the process:
56+ let _ = panic:: catch_unwind ( || abort_in_ffi ( ) ) ;
57+
58+ // If the process did not abort, the panic escaped FFI:
59+ io:: stdout ( ) . write ( b"This should never be printed.\n " ) ;
60+ let _ = io:: stdout ( ) . flush ( ) ;
61+ }
62+
63+ fn test3 ( ) {
64+ // An unsafe #[unwind(abort)] extern "C" function that panics should abort the process:
65+ let _ = panic:: catch_unwind ( || unsafe { unsafe_abort_in_ffi ( ) } ) ;
66+
67+ // If the process did not abort, the panic escaped FFI:
68+ io:: stdout ( ) . write ( b"This should never be printed.\n " ) ;
69+ let _ = io:: stdout ( ) . flush ( ) ;
70+ }
71+
3472fn main ( ) {
3573 let args: Vec < String > = env:: args ( ) . collect ( ) ;
36- if args. len ( ) > 1 && args[ 1 ] == "test" {
37- return test ( ) ;
74+ if args. len ( ) > 1 {
75+ if args[ 1 ] == "test" {
76+ return test ( ) ;
77+ }
78+ if args[ 1 ] == "test2" {
79+ return test2 ( ) ;
80+ }
81+ if args[ 1 ] == "test3" {
82+ return test3 ( ) ;
83+ }
3884 }
3985
4086 let mut p = Command :: new ( & args[ 0 ] )
@@ -43,6 +89,22 @@ fn main() {
4389 . arg ( "test" ) . spawn ( ) . unwrap ( ) ;
4490 assert ! ( !p. wait( ) . unwrap( ) . success( ) ) ;
4591
92+ let mut p = Command :: new ( & args[ 0 ] )
93+ . stdout ( Stdio :: piped ( ) )
94+ . stdin ( Stdio :: piped ( ) )
95+ . arg ( "test2" ) . spawn ( ) . unwrap ( ) ;
96+ assert ! ( !p. wait( ) . unwrap( ) . success( ) ) ;
97+
98+ let mut p = Command :: new ( & args[ 0 ] )
99+ . stdout ( Stdio :: piped ( ) )
100+ . stdin ( Stdio :: piped ( ) )
101+ . arg ( "test3" ) . spawn ( ) . unwrap ( ) ;
102+ assert ! ( !p. wait( ) . unwrap( ) . success( ) ) ;
103+
46104 // An unsafe extern "C" function that panics should let the panic escape:
47105 assert ! ( panic:: catch_unwind( || unsafe { unsafe_panic_in_ffi( ) } ) . is_err( ) ) ;
106+ assert ! ( panic:: catch_unwind( || unsafe { unsafe_panic_allow_in_ffi( ) } ) . is_err( ) ) ;
107+
108+ // A safe extern "C" unwind(allows) that panics should let the panic escape:
109+ assert ! ( panic:: catch_unwind( || nopanic_in_ffi( ) ) . is_err( ) ) ;
48110}
0 commit comments