diff options
| author | bors <bors@rust-lang.org> | 2025-05-01 04:11:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-05-01 04:11:52 +0000 |
| commit | 6e23095adf9209614a45f7f75fea36dad7b92afb (patch) | |
| tree | 557f1c5045bf650590df145d8391fb7a454c5676 /compiler/rustc_interface/src/util.rs | |
| parent | 0c33fe2c3d3eecadd17a84b110bb067288a64f1c (diff) | |
| parent | 08b27ffbe89c26d0307b524c4f920bcc704ba23d (diff) | |
| download | rust-6e23095adf9209614a45f7f75fea36dad7b92afb.tar.gz rust-6e23095adf9209614a45f7f75fea36dad7b92afb.zip | |
Auto merge of #140145 - Zoxc:job-server-proxy, r=SparrowLii
Add a jobserver proxy to ensure at least one token is always held This adds a jobserver proxy to ensure at least one token is always held by `rustc`. Currently with `-Z threads` `rustc` can temporarily give up all its tokens, causing `cargo` to spawn additional `rustc` instances beyond the job limit. The current behavior causes an issue with `cargo fix` which has a global lock preventing concurrent `rustc` instances, but it also holds a jobserver token, causing a deadlock when `rustc` gives up its token. That is fixed by this PR. Fixes https://github.com/rust-lang/rust/issues/67385. Fixes https://github.com/rust-lang/rust/issues/133873. Fixes https://github.com/rust-lang/rust/issues/140093.
Diffstat (limited to 'compiler/rustc_interface/src/util.rs')
| -rw-r--r-- | compiler/rustc_interface/src/util.rs | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 4d346b50c80..087b11fdf9d 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,11 +1,12 @@ use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::path::{Path, PathBuf}; -use std::sync::OnceLock; use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, OnceLock}; use std::{env, iter, thread}; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; +use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::sync; use rustc_metadata::{DylibError, load_symbol_from_dylib}; use rustc_middle::ty::CurrentGcx; @@ -124,7 +125,7 @@ fn init_stack_size(early_dcx: &EarlyDiagCtxt) -> usize { }) } -fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( +fn run_in_thread_with_globals<F: FnOnce(CurrentGcx, Arc<Proxy>) -> R + Send, R: Send>( thread_stack_size: usize, edition: Edition, sm_inputs: SourceMapInputs, @@ -150,7 +151,7 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( edition, extra_symbols, Some(sm_inputs), - || f(CurrentGcx::new()), + || f(CurrentGcx::new(), Proxy::new()), ) }) .unwrap() @@ -163,7 +164,10 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( }) } -pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( +pub(crate) fn run_in_thread_pool_with_globals< + F: FnOnce(CurrentGcx, Arc<Proxy>) -> R + Send, + R: Send, +>( thread_builder_diag: &EarlyDiagCtxt, edition: Edition, threads: usize, @@ -173,8 +177,8 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, ) -> R { use std::process; + use rustc_data_structures::defer; use rustc_data_structures::sync::FromDyn; - use rustc_data_structures::{defer, jobserver}; use rustc_middle::ty::tls; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::{QueryContext, break_query_cycles}; @@ -189,11 +193,11 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, edition, sm_inputs, extra_symbols, - |current_gcx| { + |current_gcx, jobserver_proxy| { // Register the thread for use with the `WorkerLocal` type. registry.register(); - f(current_gcx) + f(current_gcx, jobserver_proxy) }, ); } @@ -201,10 +205,14 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, let current_gcx = FromDyn::from(CurrentGcx::new()); let current_gcx2 = current_gcx.clone(); + let proxy = Proxy::new(); + + let proxy_ = Arc::clone(&proxy); + let proxy__ = Arc::clone(&proxy); let builder = rayon_core::ThreadPoolBuilder::new() .thread_name(|_| "rustc".to_string()) - .acquire_thread_handler(jobserver::acquire_thread) - .release_thread_handler(jobserver::release_thread) + .acquire_thread_handler(move || proxy_.acquire_thread()) + .release_thread_handler(move || proxy__.release_thread()) .num_threads(threads) .deadlock_handler(move || { // On deadlock, creates a new thread and forwards information in thread @@ -268,7 +276,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, }, // Run `f` on the first thread in the thread pool. move |pool: &rayon_core::ThreadPool| { - pool.install(|| f(current_gcx.into_inner())) + pool.install(|| f(current_gcx.into_inner(), proxy)) }, ) .unwrap() |
