diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 0d50200133cb2..23bd2dac57e3b 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -101,10 +101,11 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( threads: usize, f: F, ) -> R { - use rustc_data_structures::{jobserver, sync::FromDyn}; + use rustc_data_structures::{defer, jobserver, sync::FromDyn}; use rustc_middle::ty::tls; use rustc_query_impl::QueryCtxt; - use rustc_query_system::query::{deadlock, QueryContext}; + use rustc_query_system::query::{break_query_cycles, QueryContext}; + use std::process; let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap()); @@ -128,7 +129,19 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( let query_map = FromDyn::from(tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs())); let registry = rayon_core::Registry::current(); - thread::spawn(move || deadlock(query_map.into_inner(), ®istry)); + thread::Builder::new() + .name("rustc query cycle handler".to_string()) + .spawn(move || { + let on_panic = defer(|| { + eprintln!("query cycle handler thread panicked, aborting process"); + // We need to abort here as we failed to resolve the deadlock, + // otherwise the compiler could just hang, + process::abort(); + }); + break_query_cycles(query_map.into_inner(), ®istry); + on_panic.disable(); + }) + .unwrap(); }); if let Some(size) = get_stack_size() { builder = builder.stack_size(size); diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 1a54a2293573b..248a741af9079 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -17,10 +17,9 @@ use std::num::NonZero; use { parking_lot::{Condvar, Mutex}, rustc_data_structures::fx::FxHashSet, - rustc_data_structures::{defer, jobserver}, + rustc_data_structures::jobserver, rustc_span::DUMMY_SP, std::iter, - std::process, std::sync::Arc, }; @@ -514,12 +513,7 @@ fn remove_cycle( /// There may be multiple cycles involved in a deadlock, so this searches /// all active queries for cycles before finally resuming all the waiters at once. #[cfg(parallel_compiler)] -pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { - let on_panic = defer(|| { - eprintln!("deadlock handler panicked, aborting process"); - process::abort(); - }); - +pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) { let mut wakelist = Vec::new(); let mut jobs: Vec = query_map.keys().cloned().collect(); @@ -539,19 +533,17 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { // X to Y due to Rayon waiting and a true dependency from Y to X. The algorithm here // only considers the true dependency and won't detect a cycle. if !found_cycle { - if query_map.len() == 0 { - panic!("deadlock detected without any query!") - } else { - panic!("deadlock detected! current query map:\n{:#?}", query_map); - } + panic!( + "deadlock detected as we're unable to find a query cycle to break\n\ + current query map:\n{:#?}", + query_map + ); } // FIXME: Ensure this won't cause a deadlock before we return for waiter in wakelist.into_iter() { waiter.notify(registry); } - - on_panic.disable(); } #[inline(never)] diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 0aefe553a3435..01b9d458f1e4f 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -3,7 +3,7 @@ pub use self::plumbing::*; mod job; #[cfg(parallel_compiler)] -pub use self::job::deadlock; +pub use self::job::break_query_cycles; pub use self::job::{ print_query_stack, report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap, };