@@ -52,7 +52,49 @@ use toml::{map::Map as TomlMap, Value as TomlValue};
5252use url:: Url ;
5353use walkdir:: WalkDir ;
5454
55+ // wraps the run_inner function that actually does the work and handles any panics that occur
56+ // any langs library should never panic by itself, but other libraries used may in some rare circumstances
5557pub fn run ( ) {
58+ // run the inner function and catch any panics
59+ match std:: panic:: catch_unwind ( run_inner) {
60+ Ok ( res) => {
61+ // no panic, output was printed properly
62+ match res {
63+ Ok ( _) => {
64+ // inner returned Ok, exit with 0
65+ quit:: with_code ( 0 ) ;
66+ }
67+ Err ( _) => {
68+ // inner returned Err, exit with 1
69+ quit:: with_code ( 1 ) ;
70+ }
71+ }
72+ }
73+ Err ( err) => {
74+ // panicked, likely before any output was printed
75+ // currently only prints a message if the panic is called with str or String; this should be good enough
76+ let error_message = if let Some ( string) = err. downcast_ref :: < & str > ( ) {
77+ format ! ( "Process panicked unexpectedly with message: {}" , string)
78+ } else if let Some ( string) = err. downcast_ref :: < String > ( ) {
79+ format ! ( "Process panicked unexpectedly with message: {}" , string)
80+ } else {
81+ "Process panicked unexpectedly without an error message" . to_string ( )
82+ } ;
83+ let output = Output :: OutputData ( OutputData {
84+ status : Status :: Crashed ,
85+ message : error_message,
86+ result : OutputResult :: Error ,
87+ data : None ,
88+ } ) ;
89+ print_output ( & output, false ) . expect ( "this should never fail" ) ;
90+ quit:: with_code ( 1 ) ;
91+ }
92+ }
93+ }
94+
95+ // sets up warning and progress reporting and calls run_app and does error handling for its result
96+ // returns Ok if we should exit with code 0, Err if we should exit with 1
97+ fn run_inner ( ) -> Result < ( ) , ( ) > {
5698 let matches = app:: create_app ( ) . get_matches ( ) ;
5799 let pretty = matches. is_present ( "pretty" ) ;
58100
@@ -90,18 +132,11 @@ pub fn run() {
90132 trace : causes,
91133 } ) ,
92134 } ) ;
93- if let Err ( err) = print_output_with_file ( & error_output, pretty, sandbox_path) {
94- // the above function shouldn't fail ever, but in theory some data could
95- // have a flawed Serialize implementation, so better safe than sorry
96- let output = Output :: OutputData ( OutputData {
97- status : Status :: Crashed ,
98- message : err. to_string ( ) ,
99- result : OutputResult :: Error ,
100- data : None ,
101- } ) ;
102- print_output ( & output, pretty) . expect ( "this should never fail" ) ;
103- }
104- quit:: with_code ( 1 ) ;
135+ print_output_with_file ( & error_output, pretty, sandbox_path)
136+ . expect ( "failed to print output" ) ;
137+ Err ( ( ) )
138+ } else {
139+ Ok ( ( ) )
105140 }
106141}
107142
0 commit comments