Some tweaks to the parallel query cycle handler

This commit is contained in:
John Kåre Alsaker 2024-03-09 00:24:14 +01:00
parent a655e648a9
commit 87ab9e8c6e
3 changed files with 24 additions and 19 deletions

View File

@ -101,10 +101,11 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> 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<F: FnOnce() -> 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(), &registry));
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(), &registry);
on_panic.disable();
})
.unwrap();
});
if let Some(size) = get_stack_size() {
builder = builder.stack_size(size);

View File

@ -17,10 +17,9 @@
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<QueryJobId> = 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)]

View File

@ -3,7 +3,7 @@
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,
};