@@ -18,24 +18,25 @@ extern crate rustc_driver;
1818extern crate rustc_hir;
1919extern crate rustc_hir_analysis;
2020extern crate rustc_interface;
21- extern crate rustc_log;
2221extern crate rustc_metadata;
2322extern crate rustc_middle;
2423extern crate rustc_session;
2524extern crate rustc_span;
2625
27- use std:: env:: { self , VarError } ;
26+ use std:: env;
2827use std:: num:: NonZero ;
2928use std:: ops:: Range ;
3029use std:: path:: PathBuf ;
30+ use std:: process:: ExitCode ;
3131use std:: rc:: Rc ;
3232use std:: str:: FromStr ;
3333use std:: sync:: atomic:: { AtomicI32 , AtomicU32 , Ordering } ;
34- use std:: sync:: { Arc , Once } ;
34+ use std:: sync:: { Arc , Mutex } ;
3535
3636use miri:: {
3737 BacktraceStyle , BorrowTrackerMethod , GenmcConfig , GenmcCtx , MiriConfig , MiriEntryFnType ,
38- ProvenanceMode , RetagFields , TreeBorrowsParams , ValidationMode ,
38+ ProvenanceMode , RetagFields , TracingGuard , TreeBorrowsParams , ValidationMode ,
39+ init_early_loggers, init_late_loggers,
3940} ;
4041use rustc_abi:: ExternAbi ;
4142use rustc_data_structures:: sync;
@@ -52,9 +53,9 @@ use rustc_middle::query::LocalCrate;
5253use rustc_middle:: traits:: { ObligationCause , ObligationCauseCode } ;
5354use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
5455use rustc_middle:: util:: Providers ;
56+ use rustc_session:: EarlyDiagCtxt ;
5557use rustc_session:: config:: { CrateType , ErrorOutputType , OptLevel } ;
5658use rustc_session:: search_paths:: PathKind ;
57- use rustc_session:: { CtfeBacktrace , EarlyDiagCtxt } ;
5859use rustc_span:: def_id:: DefId ;
5960use tracing:: debug;
6061
@@ -63,6 +64,7 @@ struct MiriCompilerCalls {
6364 many_seeds : Option < ManySeedsConfig > ,
6465 /// Settings for using GenMC with Miri.
6566 genmc_config : Option < GenmcConfig > ,
67+ tracing_guard : Option < TracingGuard > ,
6668}
6769
6870struct ManySeedsConfig {
@@ -75,8 +77,9 @@ impl MiriCompilerCalls {
7577 miri_config : MiriConfig ,
7678 many_seeds : Option < ManySeedsConfig > ,
7779 genmc_config : Option < GenmcConfig > ,
80+ tracing_guard : Option < TracingGuard > ,
7881 ) -> Self {
79- Self { miri_config : Some ( miri_config) , many_seeds, genmc_config }
82+ Self { miri_config : Some ( miri_config) , many_seeds, genmc_config, tracing_guard }
8083 }
8184}
8285
@@ -156,7 +159,11 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
156159 }
157160
158161 let early_dcx = EarlyDiagCtxt :: new ( tcx. sess . opts . error_format ) ;
159- init_late_loggers ( & early_dcx, tcx) ;
162+ let tracing_guard = init_late_loggers ( & early_dcx, tcx) ;
163+ if self . tracing_guard . is_none ( ) {
164+ // either tracing_guard or self.tracing_guard are None, due to LOGGER_INITED.call_once()
165+ self . tracing_guard = tracing_guard;
166+ }
160167 if !tcx. crate_types ( ) . contains ( & CrateType :: Executable ) {
161168 tcx. dcx ( ) . fatal ( "miri only makes sense on bin crates" ) ;
162169 }
@@ -196,6 +203,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
196203 assert ! ( config. seed. is_none( ) ) ;
197204 let exit_code = sync:: IntoDynSyncSend ( AtomicI32 :: new ( rustc_driver:: EXIT_SUCCESS ) ) ;
198205 let num_failed = sync:: IntoDynSyncSend ( AtomicU32 :: new ( 0 ) ) ;
206+ let tracing_guard = sync:: IntoDynSyncSend ( Mutex :: new ( self . tracing_guard . take ( ) ) ) ;
199207 sync:: par_for_each_in ( many_seeds. seeds . clone ( ) , |seed| {
200208 let mut config = config. clone ( ) ;
201209 config. seed = Some ( ( * seed) . into ( ) ) ;
@@ -211,6 +219,10 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
211219 if return_code != rustc_driver:: EXIT_SUCCESS {
212220 eprintln ! ( "FAILING SEED: {seed}" ) ;
213221 if !many_seeds. keep_going {
222+ // drop the tracing guard before exiting, so tracing calls are flushed correctly
223+ if let Ok ( mut lock) = tracing_guard. try_lock ( ) {
224+ let _guard_being_dropped = ( * lock) . take ( ) ;
225+ }
214226 // `abort_if_errors` would actually not stop, since `par_for_each` waits for the
215227 // rest of the to finish, so we just exit immediately.
216228 std:: process:: exit ( return_code) ;
@@ -223,6 +235,9 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
223235 if num_failed > 0 {
224236 eprintln ! ( "{num_failed}/{total} SEEDS FAILED" , total = many_seeds. seeds. count( ) ) ;
225237 }
238+ // drop the tracing guard before exiting, so tracing calls are flushed correctly
239+ #[ allow( clippy:: drop_non_drop) ]
240+ std:: mem:: drop ( tracing_guard) ;
226241 std:: process:: exit ( exit_code. 0 . into_inner ( ) ) ;
227242 } else {
228243 let return_code = miri:: eval_entry ( tcx, entry_def_id, entry_type, & config, None )
@@ -232,6 +247,10 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
232247 tcx. dcx ( ) . abort_if_errors ( ) ;
233248 rustc_driver:: EXIT_FAILURE
234249 } ) ;
250+
251+ // drop the tracing guard before exiting, so tracing calls are flushed correctly
252+ #[ allow( clippy:: drop_non_drop) ]
253+ std:: mem:: drop ( self . tracing_guard . take ( ) ) ;
235254 std:: process:: exit ( return_code) ;
236255 }
237256
@@ -336,74 +355,19 @@ macro_rules! show_error {
336355 ( $( $tt: tt) * ) => { show_error( & format_args!( $( $tt) * ) ) } ;
337356}
338357
339- fn rustc_logger_config ( ) -> rustc_log:: LoggerConfig {
340- // Start with the usual env vars.
341- let mut cfg = rustc_log:: LoggerConfig :: from_env ( "RUSTC_LOG" ) ;
342-
343- // Overwrite if MIRI_LOG is set.
344- if let Ok ( var) = env:: var ( "MIRI_LOG" ) {
345- // MIRI_LOG serves as default for RUSTC_LOG, if that is not set.
346- if matches ! ( cfg. filter, Err ( VarError :: NotPresent ) ) {
347- // We try to be a bit clever here: if `MIRI_LOG` is just a single level
348- // used for everything, we only apply it to the parts of rustc that are
349- // CTFE-related. Otherwise, we use it verbatim for `RUSTC_LOG`.
350- // This way, if you set `MIRI_LOG=trace`, you get only the right parts of
351- // rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_const_eval::interpret=debug`.
352- if tracing:: Level :: from_str ( & var) . is_ok ( ) {
353- cfg. filter = Ok ( format ! (
354- "rustc_middle::mir::interpret={var},rustc_const_eval::interpret={var},miri={var}"
355- ) ) ;
356- } else {
357- cfg. filter = Ok ( var) ;
358- }
359- }
360- }
361-
362- cfg
363- }
364-
365- /// The global logger can only be set once per process, so track
366- /// whether that already happened.
367- static LOGGER_INITED : Once = Once :: new ( ) ;
368-
369- fn init_early_loggers ( early_dcx : & EarlyDiagCtxt ) {
370- // We only initialize `rustc` if the env var is set (so the user asked for it).
371- // If it is not set, we avoid initializing now so that we can initialize later with our custom
372- // settings, and *not* log anything for what happens before `miri` starts interpreting.
373- if env:: var_os ( "RUSTC_LOG" ) . is_some ( ) {
374- LOGGER_INITED . call_once ( || {
375- rustc_driver:: init_logger ( early_dcx, rustc_logger_config ( ) ) ;
376- } ) ;
377- }
378- }
379-
380- fn init_late_loggers ( early_dcx : & EarlyDiagCtxt , tcx : TyCtxt < ' _ > ) {
381- // If the logger is not yet initialized, initialize it.
382- LOGGER_INITED . call_once ( || {
383- rustc_driver:: init_logger ( early_dcx, rustc_logger_config ( ) ) ;
384- } ) ;
385-
386- // If `MIRI_BACKTRACE` is set and `RUSTC_CTFE_BACKTRACE` is not, set `RUSTC_CTFE_BACKTRACE`.
387- // Do this late, so we ideally only apply this to Miri's errors.
388- if let Some ( val) = env:: var_os ( "MIRI_BACKTRACE" ) {
389- let ctfe_backtrace = match & * val. to_string_lossy ( ) {
390- "immediate" => CtfeBacktrace :: Immediate ,
391- "0" => CtfeBacktrace :: Disabled ,
392- _ => CtfeBacktrace :: Capture ,
393- } ;
394- * tcx. sess . ctfe_backtrace . borrow_mut ( ) = ctfe_backtrace;
395- }
396- }
397-
398358/// Execute a compiler with the given CLI arguments and callbacks.
359+ /// Does not call [std::process::exit] directly, but rather returns an [ExitCode],
360+ /// to allow the tracing guard to be dropped before exiting.
361+ #[ must_use]
399362fn run_compiler_and_exit (
400363 args : & [ String ] ,
401364 callbacks : & mut ( dyn rustc_driver:: Callbacks + Send ) ,
402- ) -> ! {
403- // Invoke compiler, and handle return code.
404- let exit_code =
405- rustc_driver:: catch_with_exit_code ( move || rustc_driver:: run_compiler ( args, callbacks) ) ;
406- std:: process:: exit ( exit_code)
365+ ) -> ExitCode {
366+ // Invoke compiler, catch any unwinding panics and handle return code.
367+ match rustc_driver:: catch_fatal_errors ( move || rustc_driver:: run_compiler ( args, callbacks) ) {
368+ Ok ( ( ) ) => ExitCode :: SUCCESS ,
369+ _ => ExitCode :: FAILURE ,
370+ }
407371}
408372
409373/// Parses a comma separated list of `T` from the given string:
@@ -471,7 +435,7 @@ fn jemalloc_magic() {
471435 }
472436}
473437
474- fn main ( ) {
438+ fn main ( ) -> ExitCode {
475439 #[ cfg( any( target_os = "linux" , target_os = "macos" ) ) ]
476440 jemalloc_magic ( ) ;
477441
@@ -515,15 +479,12 @@ fn main() {
515479 }
516480
517481 // We cannot use `rustc_driver::main` as we want it to use `args` as the CLI arguments.
518- run_compiler_and_exit ( & args, & mut MiriBeRustCompilerCalls { target_crate } )
482+ return run_compiler_and_exit ( & args, & mut MiriBeRustCompilerCalls { target_crate } ) ;
519483 }
520484
521485 // Add an ICE bug report hook.
522486 rustc_driver:: install_ice_hook ( "https://github.com/rust-lang/miri/issues/new" , |_| ( ) ) ;
523487
524- // Init loggers the Miri way.
525- init_early_loggers ( & early_dcx) ;
526-
527488 // Parse our arguments and split them across `rustc` and `miri`.
528489 let mut many_seeds: Option < Range < u32 > > = None ;
529490 let mut many_seeds_keep_going = false ;
@@ -793,6 +754,11 @@ fn main() {
793754 ) ;
794755 } ;
795756
757+ // Init loggers the Miri way. Do so after arguments have been parsed, so no tracing file is
758+ // created if argument parsing fails, and also so that we don't have to worry about dropping
759+ // the guard before calling std::process::exit() in show_error!().
760+ let tracing_guard = init_early_loggers ( & early_dcx) ;
761+
796762 debug ! ( "rustc arguments: {:?}" , rustc_args) ;
797763 debug ! ( "crate arguments: {:?}" , miri_config. args) ;
798764 #[ cfg( target_os = "linux" ) ]
@@ -807,6 +773,6 @@ fn main() {
807773 }
808774 run_compiler_and_exit (
809775 & rustc_args,
810- & mut MiriCompilerCalls :: new ( miri_config, many_seeds, genmc_config) ,
776+ & mut MiriCompilerCalls :: new ( miri_config, many_seeds, genmc_config, tracing_guard ) ,
811777 )
812778}
0 commit comments