Skip to content

Commit 8c52a83

Browse files
committed
Auto merge of #98570 - SparrowLii:deadlock, r=cjgillot
get rid of `tcx` in deadlock handler when parallel compilation This is a very obscure and hard-to-trace problem that affects thread scheduling. If we copy `tcx` to the deadlock handler thread, it will perform unpredictable behavior and cause very weird problems when executing `try_collect_active_jobs`(For example, the deadlock handler thread suddenly preempts the content of the blocked worker thread and executes the unknown judgment branch, like #94654). Fortunately we can avoid this behavior by precomputing `query_map`. This change fixes the following ui tests failure on my environment when set `parallel-compiler = true`: ``` [ui] src/test\ui\async-await\no-const-async.rs [ui] src/test\ui\infinite\infinite-struct.rs [ui] src/test\ui\infinite\infinite-tag-type-recursion.rs [ui] src/test\ui\issues\issue-3008-1.rs [ui] src/test\ui\issues\issue-3008-2.rs [ui] src/test\ui\issues\issue-32326.rs [ui] src/test\ui\issues\issue-57271.rs [ui] src/test\ui\issues\issue-72554.rs [ui] src/test\ui\parser\fn-header-semantic-fail.rs [ui] src/test\ui\union\union-nonrepresentable.rs ``` Updates #75760 Fixes #94654
2 parents 5f98537 + fbca21e commit 8c52a83

File tree

4 files changed

+9
-21
lines changed

4 files changed

+9
-21
lines changed

Diff for: compiler/rustc_interface/src/util.rs

+6-14
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_errors::registry::Registry;
1010
use rustc_middle::ty::tls;
1111
use rustc_parse::validate_attr;
1212
#[cfg(parallel_compiler)]
13-
use rustc_query_impl::QueryCtxt;
13+
use rustc_query_impl::{QueryContext, QueryCtxt};
1414
use rustc_session as session;
1515
use rustc_session::config::CheckCfg;
1616
use rustc_session::config::{self, CrateType};
@@ -166,20 +166,12 @@ pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
166166
unsafe fn handle_deadlock() {
167167
let registry = rustc_rayon_core::Registry::current();
168168

169-
let context = tls::get_tlv();
170-
assert!(context != 0);
171-
rustc_data_structures::sync::assert_sync::<tls::ImplicitCtxt<'_, '_>>();
172-
let icx: &tls::ImplicitCtxt<'_, '_> = &*(context as *const tls::ImplicitCtxt<'_, '_>);
173-
174-
let session_globals = rustc_span::with_session_globals(|sg| sg as *const _);
175-
let session_globals = &*session_globals;
176-
thread::spawn(move || {
177-
tls::enter_context(icx, |_| {
178-
rustc_span::set_session_globals_then(session_globals, || {
179-
tls::with(|tcx| QueryCtxt::from_tcx(tcx).deadlock(&registry))
180-
})
181-
});
169+
let query_map = tls::with(|tcx| {
170+
QueryCtxt::from_tcx(tcx)
171+
.try_collect_active_jobs()
172+
.expect("active jobs shouldn't be locked in deadlock handler")
182173
});
174+
thread::spawn(move || rustc_query_impl::deadlock(query_map, &registry));
183175
}
184176

185177
#[cfg(parallel_compiler)]

Diff for: compiler/rustc_query_impl/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ use rustc_span::Span;
2727
mod plumbing;
2828
pub use plumbing::QueryCtxt;
2929
use rustc_query_system::query::*;
30+
#[cfg(parallel_compiler)]
31+
pub use rustc_query_system::query::{deadlock, QueryContext};
3032

3133
mod keys;
3234
use keys::Key;

Diff for: compiler/rustc_query_impl/src/plumbing.rs

-5
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,6 @@ impl<'tcx> QueryCtxt<'tcx> {
132132
self.queries.on_disk_cache.as_ref()
133133
}
134134

135-
#[cfg(parallel_compiler)]
136-
pub unsafe fn deadlock(self, registry: &rustc_rayon_core::Registry) {
137-
rustc_query_system::query::deadlock(self, registry)
138-
}
139-
140135
pub(super) fn encode_query_results(
141136
self,
142137
encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>,

Diff for: compiler/rustc_query_system/src/query/job.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -492,14 +492,13 @@ fn remove_cycle(
492492
/// There may be multiple cycles involved in a deadlock, so this searches
493493
/// all active queries for cycles before finally resuming all the waiters at once.
494494
#[cfg(parallel_compiler)]
495-
pub fn deadlock<CTX: QueryContext>(tcx: CTX, registry: &rayon_core::Registry) {
495+
pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) {
496496
let on_panic = OnDrop(|| {
497497
eprintln!("deadlock handler panicked, aborting process");
498498
process::abort();
499499
});
500500

501501
let mut wakelist = Vec::new();
502-
let query_map = tcx.try_collect_active_jobs().unwrap();
503502
let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect();
504503

505504
let mut found_cycle = false;

0 commit comments

Comments
 (0)