@@ -22,6 +22,26 @@ extern "C" fn panic_in_ffi() {
22
22
panic ! ( "Test" ) ;
23
23
}
24
24
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
+
25
45
fn test ( ) {
26
46
// A safe extern "C" function that panics should abort the process:
27
47
let _ = panic:: catch_unwind ( || panic_in_ffi ( ) ) ;
@@ -31,10 +51,36 @@ fn test() {
31
51
let _ = io:: stdout ( ) . flush ( ) ;
32
52
}
33
53
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
+
34
72
fn main ( ) {
35
73
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
+ }
38
84
}
39
85
40
86
let mut p = Command :: new ( & args[ 0 ] )
@@ -43,6 +89,22 @@ fn main() {
43
89
. arg ( "test" ) . spawn ( ) . unwrap ( ) ;
44
90
assert ! ( !p. wait( ) . unwrap( ) . success( ) ) ;
45
91
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
+
46
104
// An unsafe extern "C" function that panics should let the panic escape:
47
105
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( ) ) ;
48
110
}
0 commit comments