@@ -18,24 +18,25 @@ extern crate rustc_driver;
18
18
extern crate rustc_hir;
19
19
extern crate rustc_hir_analysis;
20
20
extern crate rustc_interface;
21
- extern crate rustc_log;
22
21
extern crate rustc_metadata;
23
22
extern crate rustc_middle;
24
23
extern crate rustc_session;
25
24
extern crate rustc_span;
26
25
27
- use std:: env:: { self , VarError } ;
26
+ use std:: env;
28
27
use std:: num:: NonZero ;
29
28
use std:: ops:: Range ;
30
29
use std:: path:: PathBuf ;
30
+ use std:: process:: ExitCode ;
31
31
use std:: rc:: Rc ;
32
32
use std:: str:: FromStr ;
33
33
use std:: sync:: atomic:: { AtomicI32 , AtomicU32 , Ordering } ;
34
- use std:: sync:: { Arc , Once } ;
34
+ use std:: sync:: { Arc , Mutex } ;
35
35
36
36
use miri:: {
37
37
BacktraceStyle , BorrowTrackerMethod , GenmcConfig , GenmcCtx , MiriConfig , MiriEntryFnType ,
38
- ProvenanceMode , RetagFields , TreeBorrowsParams , ValidationMode ,
38
+ ProvenanceMode , RetagFields , TracingGuard , TreeBorrowsParams , ValidationMode ,
39
+ init_early_loggers, init_late_loggers,
39
40
} ;
40
41
use rustc_abi:: ExternAbi ;
41
42
use rustc_data_structures:: sync;
@@ -52,9 +53,9 @@ use rustc_middle::query::LocalCrate;
52
53
use rustc_middle:: traits:: { ObligationCause , ObligationCauseCode } ;
53
54
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
54
55
use rustc_middle:: util:: Providers ;
56
+ use rustc_session:: EarlyDiagCtxt ;
55
57
use rustc_session:: config:: { CrateType , ErrorOutputType , OptLevel } ;
56
58
use rustc_session:: search_paths:: PathKind ;
57
- use rustc_session:: { CtfeBacktrace , EarlyDiagCtxt } ;
58
59
use rustc_span:: def_id:: DefId ;
59
60
use tracing:: debug;
60
61
@@ -63,6 +64,7 @@ struct MiriCompilerCalls {
63
64
many_seeds : Option < ManySeedsConfig > ,
64
65
/// Settings for using GenMC with Miri.
65
66
genmc_config : Option < GenmcConfig > ,
67
+ tracing_guard : Option < TracingGuard > ,
66
68
}
67
69
68
70
struct ManySeedsConfig {
@@ -75,8 +77,9 @@ impl MiriCompilerCalls {
75
77
miri_config : MiriConfig ,
76
78
many_seeds : Option < ManySeedsConfig > ,
77
79
genmc_config : Option < GenmcConfig > ,
80
+ tracing_guard : Option < TracingGuard > ,
78
81
) -> 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 }
80
83
}
81
84
}
82
85
@@ -156,7 +159,11 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
156
159
}
157
160
158
161
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
+ }
160
167
if !tcx. crate_types ( ) . contains ( & CrateType :: Executable ) {
161
168
tcx. dcx ( ) . fatal ( "miri only makes sense on bin crates" ) ;
162
169
}
@@ -196,6 +203,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
196
203
assert ! ( config. seed. is_none( ) ) ;
197
204
let exit_code = sync:: IntoDynSyncSend ( AtomicI32 :: new ( rustc_driver:: EXIT_SUCCESS ) ) ;
198
205
let num_failed = sync:: IntoDynSyncSend ( AtomicU32 :: new ( 0 ) ) ;
206
+ let tracing_guard = sync:: IntoDynSyncSend ( Mutex :: new ( self . tracing_guard . take ( ) ) ) ;
199
207
sync:: par_for_each_in ( many_seeds. seeds . clone ( ) , |seed| {
200
208
let mut config = config. clone ( ) ;
201
209
config. seed = Some ( ( * seed) . into ( ) ) ;
@@ -211,6 +219,10 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
211
219
if return_code != rustc_driver:: EXIT_SUCCESS {
212
220
eprintln ! ( "FAILING SEED: {seed}" ) ;
213
221
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
+ }
214
226
// `abort_if_errors` would actually not stop, since `par_for_each` waits for the
215
227
// rest of the to finish, so we just exit immediately.
216
228
std:: process:: exit ( return_code) ;
@@ -223,6 +235,9 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
223
235
if num_failed > 0 {
224
236
eprintln ! ( "{num_failed}/{total} SEEDS FAILED" , total = many_seeds. seeds. count( ) ) ;
225
237
}
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) ;
226
241
std:: process:: exit ( exit_code. 0 . into_inner ( ) ) ;
227
242
} else {
228
243
let return_code = miri:: eval_entry ( tcx, entry_def_id, entry_type, & config, None )
@@ -232,6 +247,10 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
232
247
tcx. dcx ( ) . abort_if_errors ( ) ;
233
248
rustc_driver:: EXIT_FAILURE
234
249
} ) ;
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 ( ) ) ;
235
254
std:: process:: exit ( return_code) ;
236
255
}
237
256
@@ -336,74 +355,19 @@ macro_rules! show_error {
336
355
( $( $tt: tt) * ) => { show_error( & format_args!( $( $tt) * ) ) } ;
337
356
}
338
357
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
-
398
358
/// 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]
399
362
fn run_compiler_and_exit (
400
363
args : & [ String ] ,
401
364
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
+ }
407
371
}
408
372
409
373
/// Parses a comma separated list of `T` from the given string:
@@ -471,7 +435,7 @@ fn jemalloc_magic() {
471
435
}
472
436
}
473
437
474
- fn main ( ) {
438
+ fn main ( ) -> ExitCode {
475
439
#[ cfg( any( target_os = "linux" , target_os = "macos" ) ) ]
476
440
jemalloc_magic ( ) ;
477
441
@@ -515,15 +479,12 @@ fn main() {
515
479
}
516
480
517
481
// 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 } ) ;
519
483
}
520
484
521
485
// Add an ICE bug report hook.
522
486
rustc_driver:: install_ice_hook ( "https://github.com/rust-lang/miri/issues/new" , |_| ( ) ) ;
523
487
524
- // Init loggers the Miri way.
525
- init_early_loggers ( & early_dcx) ;
526
-
527
488
// Parse our arguments and split them across `rustc` and `miri`.
528
489
let mut many_seeds: Option < Range < u32 > > = None ;
529
490
let mut many_seeds_keep_going = false ;
@@ -793,6 +754,11 @@ fn main() {
793
754
) ;
794
755
} ;
795
756
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
+
796
762
debug ! ( "rustc arguments: {:?}" , rustc_args) ;
797
763
debug ! ( "crate arguments: {:?}" , miri_config. args) ;
798
764
#[ cfg( target_os = "linux" ) ]
@@ -807,6 +773,6 @@ fn main() {
807
773
}
808
774
run_compiler_and_exit (
809
775
& rustc_args,
810
- & mut MiriCompilerCalls :: new ( miri_config, many_seeds, genmc_config) ,
776
+ & mut MiriCompilerCalls :: new ( miri_config, many_seeds, genmc_config, tracing_guard ) ,
811
777
)
812
778
}
0 commit comments