Rollup merge of #122215 - Zoxc:cycle-detect-names, r=oli-obk
Some tweaks to the parallel query cycle handler This renames `deadlock` to `break_query_cycles`. The abort logic is moved next to the thread spawning and gives the thread a name. Fixes https://github.com/rust-lang/rust/issues/122035. r? ```@oli-obk```
This commit is contained in:
commit
dc7a9f6c7f
3 changed files with 24 additions and 19 deletions
|
@ -101,10 +101,11 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
|
||||||
threads: usize,
|
threads: usize,
|
||||||
f: F,
|
f: F,
|
||||||
) -> R {
|
) -> R {
|
||||||
use rustc_data_structures::{jobserver, sync::FromDyn};
|
use rustc_data_structures::{defer, jobserver, sync::FromDyn};
|
||||||
use rustc_middle::ty::tls;
|
use rustc_middle::ty::tls;
|
||||||
use rustc_query_impl::QueryCtxt;
|
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());
|
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 =
|
let query_map =
|
||||||
FromDyn::from(tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs()));
|
FromDyn::from(tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs()));
|
||||||
let registry = rayon_core::Registry::current();
|
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() {
|
if let Some(size) = get_stack_size() {
|
||||||
builder = builder.stack_size(size);
|
builder = builder.stack_size(size);
|
||||||
|
|
|
@ -17,10 +17,9 @@ use std::num::NonZero;
|
||||||
use {
|
use {
|
||||||
parking_lot::{Condvar, Mutex},
|
parking_lot::{Condvar, Mutex},
|
||||||
rustc_data_structures::fx::FxHashSet,
|
rustc_data_structures::fx::FxHashSet,
|
||||||
rustc_data_structures::{defer, jobserver},
|
rustc_data_structures::jobserver,
|
||||||
rustc_span::DUMMY_SP,
|
rustc_span::DUMMY_SP,
|
||||||
std::iter,
|
std::iter,
|
||||||
std::process,
|
|
||||||
std::sync::Arc,
|
std::sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -514,12 +513,7 @@ fn remove_cycle(
|
||||||
/// There may be multiple cycles involved in a deadlock, so this searches
|
/// 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.
|
/// all active queries for cycles before finally resuming all the waiters at once.
|
||||||
#[cfg(parallel_compiler)]
|
#[cfg(parallel_compiler)]
|
||||||
pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) {
|
pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) {
|
||||||
let on_panic = defer(|| {
|
|
||||||
eprintln!("deadlock handler panicked, aborting process");
|
|
||||||
process::abort();
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut wakelist = Vec::new();
|
let mut wakelist = Vec::new();
|
||||||
let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect();
|
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
|
// 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.
|
// only considers the true dependency and won't detect a cycle.
|
||||||
if !found_cycle {
|
if !found_cycle {
|
||||||
if query_map.len() == 0 {
|
panic!(
|
||||||
panic!("deadlock detected without any query!")
|
"deadlock detected as we're unable to find a query cycle to break\n\
|
||||||
} else {
|
current query map:\n{:#?}",
|
||||||
panic!("deadlock detected! current query map:\n{:#?}", query_map);
|
query_map
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Ensure this won't cause a deadlock before we return
|
// FIXME: Ensure this won't cause a deadlock before we return
|
||||||
for waiter in wakelist.into_iter() {
|
for waiter in wakelist.into_iter() {
|
||||||
waiter.notify(registry);
|
waiter.notify(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
on_panic.disable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
|
|
|
@ -3,7 +3,7 @@ pub use self::plumbing::*;
|
||||||
|
|
||||||
mod job;
|
mod job;
|
||||||
#[cfg(parallel_compiler)]
|
#[cfg(parallel_compiler)]
|
||||||
pub use self::job::deadlock;
|
pub use self::job::break_query_cycles;
|
||||||
pub use self::job::{
|
pub use self::job::{
|
||||||
print_query_stack, report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap,
|
print_query_stack, report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue