Skip to content

Commit 1f3976a

Browse files
committed
Give deadlock handler access to GlobalCtxt
1 parent f7cb53e commit 1f3976a

File tree

3 files changed

+43
-17
lines changed

3 files changed

+43
-17
lines changed

compiler/rustc_interface/src/interface.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_span::symbol::sym;
2424
use rustc_span::FileName;
2525
use std::path::PathBuf;
2626
use std::result;
27+
use std::sync::atomic::AtomicPtr;
2728
use std::sync::Arc;
2829

2930
pub type Result<T> = result::Result<T, ErrorGuaranteed>;
@@ -39,6 +40,7 @@ pub struct Compiler {
3940
pub sess: Session,
4041
pub codegen_backend: Box<dyn CodegenBackend>,
4142
pub(crate) override_queries: Option<fn(&Session, &mut Providers)>,
43+
pub compiler_for_deadlock_handler: Arc<AtomicPtr<()>>,
4244
}
4345

4446
/// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`.
@@ -328,23 +330,27 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
328330
let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
329331
early_dcx.initialize_checked_jobserver();
330332

333+
let compiler_for_deadlock_handler = Arc::<AtomicPtr<_>>::default();
334+
331335
util::run_in_thread_pool_with_globals(
332336
config.opts.edition,
333337
config.opts.unstable_opts.threads,
338+
compiler_for_deadlock_handler.clone(),
334339
|| {
335340
crate::callbacks::setup_callbacks();
336341

337342
let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
338343

339-
let codegen_backend = if let Some(make_codegen_backend) = config.make_codegen_backend {
340-
make_codegen_backend(&config.opts)
341-
} else {
342-
util::get_codegen_backend(
343-
&early_dcx,
344-
&config.opts.maybe_sysroot,
345-
config.opts.unstable_opts.codegen_backend.as_deref(),
346-
)
347-
};
344+
let codegen_backend: Box<dyn CodegenBackend> =
345+
if let Some(make_codegen_backend) = config.make_codegen_backend {
346+
make_codegen_backend(&config.opts)
347+
} else {
348+
util::get_codegen_backend(
349+
&early_dcx,
350+
&config.opts.maybe_sysroot,
351+
config.opts.unstable_opts.codegen_backend.as_deref(),
352+
)
353+
};
348354

349355
let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
350356

@@ -419,8 +425,12 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
419425
}
420426
sess.lint_store = Some(Lrc::new(lint_store));
421427

422-
let compiler =
423-
Compiler { sess, codegen_backend, override_queries: config.override_queries };
428+
let compiler = Arc::new(Compiler {
429+
sess,
430+
codegen_backend,
431+
override_queries: config.override_queries,
432+
compiler_for_deadlock_handler,
433+
});
424434

425435
rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
426436
// There are two paths out of `f`.

compiler/rustc_interface/src/queries.rs

+10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_session::Session;
2424
use rustc_span::symbol::sym;
2525
use std::any::Any;
2626
use std::cell::{RefCell, RefMut};
27+
use std::sync::atomic::Ordering;
2728
use std::sync::Arc;
2829

2930
/// Represent the result of a query.
@@ -160,6 +161,10 @@ impl<'tcx> Queries<'tcx> {
160161
&self.hir_arena,
161162
);
162163

164+
self.compiler
165+
.compiler_for_deadlock_handler
166+
.store(qcx as *const _ as *mut _, Ordering::Relaxed);
167+
163168
qcx.enter(|tcx| {
164169
let feed = tcx.feed_local_crate();
165170
feed.crate_name(crate_name);
@@ -311,6 +316,11 @@ impl Compiler {
311316
{
312317
// Must declare `_timer` first so that it is dropped after `queries`.
313318
let mut _timer = None;
319+
let _guard = rustc_data_structures::defer(|| {
320+
// If we got here, there was no deadlock, so we can't be in a situation where a deadlock handler
321+
// is accessing the `GlobalCtxt`.
322+
self.compiler_for_deadlock_handler.store(std::ptr::null_mut(), Ordering::Relaxed);
323+
});
314324
let queries = Queries::new(self);
315325
let ret = f(&queries);
316326

compiler/rustc_interface/src/util.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use session::EarlyDiagCtxt;
1818
use std::env;
1919
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
2020
use std::path::{Path, PathBuf};
21-
use std::sync::atomic::{AtomicBool, Ordering};
22-
use std::sync::OnceLock;
21+
use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
22+
use std::sync::{Arc, OnceLock};
2323
use std::thread;
2424

2525
/// Function pointer type that constructs a new CodegenBackend.
@@ -90,6 +90,7 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>(
9090
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
9191
edition: Edition,
9292
_threads: usize,
93+
_compiler: Arc<AtomicPtr<()>>,
9394
f: F,
9495
) -> R {
9596
run_in_thread_with_globals(edition, f)
@@ -99,10 +100,11 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
99100
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
100101
edition: Edition,
101102
threads: usize,
103+
compiler: Arc<AtomicPtr<()>>,
102104
f: F,
103105
) -> R {
104106
use rustc_data_structures::{jobserver, sync::FromDyn};
105-
use rustc_middle::ty::tls;
107+
use rustc_middle::ty::GlobalCtxt;
106108
use rustc_query_impl::QueryCtxt;
107109
use rustc_query_system::query::{deadlock, QueryContext};
108110

@@ -122,11 +124,15 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
122124
.acquire_thread_handler(jobserver::acquire_thread)
123125
.release_thread_handler(jobserver::release_thread)
124126
.num_threads(threads)
125-
.deadlock_handler(|| {
127+
.deadlock_handler(move || {
128+
let compiler = compiler.load(Ordering::Relaxed);
129+
assert!(!compiler.is_null());
130+
let compiler = compiler as *const GlobalCtxt<'_>;
126131
// On deadlock, creates a new thread and forwards information in thread
127132
// locals to it. The new thread runs the deadlock handler.
128-
let query_map =
129-
FromDyn::from(tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs()));
133+
let query_map = FromDyn::from(unsafe {
134+
(*compiler).enter(|tcx| QueryCtxt::new(tcx).collect_active_jobs())
135+
});
130136
let registry = rayon_core::Registry::current();
131137
thread::spawn(move || deadlock(query_map.into_inner(), &registry));
132138
});

0 commit comments

Comments
 (0)