11use std:: any:: Any ;
22use std:: process:: ExitStatus ;
33
4+ #[ cfg( target_os = "fuchsia" ) ]
5+ use std:: os:: fuchsia:: process:: { ExitStatusExt as _, ZX_TASK_RETCODE_EXCEPTION_KILL } ;
46#[ cfg( unix) ]
5- use std:: os:: unix:: process:: ExitStatusExt ;
7+ use std:: os:: unix:: process:: ExitStatusExt as _ ;
68
79use super :: bench:: BenchSamples ;
810use super :: options:: ShouldPanic ;
@@ -21,14 +23,6 @@ pub const TR_OK: i32 = 50;
2123#[ cfg( windows) ]
2224const STATUS_FAIL_FAST_EXCEPTION : i32 = 0xC0000409u32 as i32 ;
2325
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-
3226#[ derive( Debug , Clone , PartialEq ) ]
3327pub enum TestResult {
3428 TrOk ,
@@ -101,10 +95,28 @@ pub fn get_result_from_exit_code(
10195 time_opts : & Option < time:: TestTimeOptions > ,
10296 exec_time : & Option < time:: TestExecTime > ,
10397) -> 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 ( ) {
105113 Some ( TR_OK ) => TestResult :: TrOk ,
106114 #[ cfg( windows) ]
107115 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 ,
108120 #[ cfg( unix) ]
109121 None => match status. signal ( ) {
110122 Some ( libc:: SIGABRT ) => TestResult :: TrFailed ,
@@ -113,16 +125,9 @@ pub fn get_result_from_exit_code(
113125 }
114126 None => unreachable ! ( "status.code() returned None but status.signal() was None" ) ,
115127 } ,
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 ,
119128 #[ cfg( not( unix) ) ]
120129 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+ } ) ;
126131
127132 // If test is already failed (or allowed to fail), do not change the result.
128133 if result != TestResult :: TrOk {
0 commit comments