Some tweaks to the parallel query cycle handler
This commit is contained in:
parent
a655e648a9
commit
87ab9e8c6e
@ -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(), ®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);
|
||||
|
@ -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)]
|
||||
|
@ -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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user