1
1
use std:: any:: Any ;
2
2
use std:: process:: ExitStatus ;
3
3
4
+ #[ cfg( target_os = "fuchsia" ) ]
5
+ use std:: os:: fuchsia:: process:: { ExitStatusExt as _, ZX_TASK_RETCODE_EXCEPTION_KILL } ;
4
6
#[ cfg( unix) ]
5
- use std:: os:: unix:: process:: ExitStatusExt ;
7
+ use std:: os:: unix:: process:: ExitStatusExt as _ ;
6
8
7
9
use super :: bench:: BenchSamples ;
8
10
use super :: options:: ShouldPanic ;
@@ -21,14 +23,6 @@ pub const TR_OK: i32 = 50;
21
23
#[ cfg( windows) ]
22
24
const STATUS_FAIL_FAST_EXCEPTION : i32 = 0xC0000409u32 as i32 ;
23
25
24
- // On Zircon (the Fuchsia kernel), an abort from userspace calls the
25
- // LLVM implementation of __builtin_trap(), e.g., ud2 on x86, which
26
- // raises a kernel exception. If a userspace process does not
27
- // otherwise arrange exception handling, the kernel kills the process
28
- // with this return code.
29
- #[ cfg( target_os = "fuchsia" ) ]
30
- const ZX_TASK_RETCODE_EXCEPTION_KILL : i32 = -1028 ;
31
-
32
26
#[ derive( Debug , Clone , PartialEq ) ]
33
27
pub enum TestResult {
34
28
TrOk ,
@@ -101,10 +95,28 @@ pub fn get_result_from_exit_code(
101
95
time_opts : & Option < time:: TestTimeOptions > ,
102
96
exec_time : & Option < time:: TestExecTime > ,
103
97
) -> TestResult {
104
- let result = match status. code ( ) {
98
+ // Upon a panic, a Fuchsia process will trigger a kernel exception
99
+ // that, if uncaught, will cause the kernel to kill the process with
100
+ // ZX_TASK_RETCODE_EXCEPTION_KILL. Though unlikely, the same code could be
101
+ // returned for other unhandled exceptions too. Even in those cases the test
102
+ // should still fail and the printed stacktrace from the kernel should
103
+ // sufficienly compensate for omitting this return code from test output.
104
+ #[ cfg( target_os = "fuchsia" ) ]
105
+ let result = match status. task_retcode ( ) {
106
+ Some ( ZX_TASK_RETCODE_EXCEPTION_KILL ) => Some ( TestResult :: TrFailed ) ,
107
+ _ => None ,
108
+ } ;
109
+ #[ cfg( not( target_os = "fuchsia" ) ) ]
110
+ let result: Option < TestResult > = None ;
111
+
112
+ let result = result. unwrap_or_else ( || match status. code ( ) {
105
113
Some ( TR_OK ) => TestResult :: TrOk ,
106
114
#[ cfg( windows) ]
107
115
Some ( STATUS_FAIL_FAST_EXCEPTION ) => TestResult :: TrFailed ,
116
+ #[ cfg( any( windows, unix) ) ]
117
+ Some ( code) => TestResult :: TrFailedMsg ( format ! ( "got unexpected return code {code}" ) ) ,
118
+ #[ cfg( not( any( windows, unix) ) ) ]
119
+ Some ( _) => TestResult :: TrFailed ,
108
120
#[ cfg( unix) ]
109
121
None => match status. signal ( ) {
110
122
Some ( libc:: SIGABRT ) => TestResult :: TrFailed ,
@@ -113,16 +125,9 @@ pub fn get_result_from_exit_code(
113
125
}
114
126
None => unreachable ! ( "status.code() returned None but status.signal() was None" ) ,
115
127
} ,
116
- // Upon an abort, Fuchsia returns the status code ZX_TASK_RETCODE_EXCEPTION_KILL.
117
- #[ cfg( target_os = "fuchsia" ) ]
118
- Some ( ZX_TASK_RETCODE_EXCEPTION_KILL ) => TestResult :: TrFailed ,
119
128
#[ cfg( not( unix) ) ]
120
129
None => TestResult :: TrFailedMsg ( format ! ( "unknown return code" ) ) ,
121
- #[ cfg( any( windows, unix) ) ]
122
- Some ( code) => TestResult :: TrFailedMsg ( format ! ( "got unexpected return code {code}" ) ) ,
123
- #[ cfg( not( any( windows, unix) ) ) ]
124
- Some ( _) => TestResult :: TrFailed ,
125
- } ;
130
+ } ) ;
126
131
127
132
// If test is already failed (or allowed to fail), do not change the result.
128
133
if result != TestResult :: TrOk {
0 commit comments