Change:
I noticed that when parallel rustc panics due to deadlock, it would say instead of . Is this intended?
Hm, I did recently land but I'm not sure if it would cause this issue. It should only affect threads that Rust doesn't create itself and in any case it switches the default name from (which gets rendered as ) to the OS thread name (if available). So if anything I'd have thought it would have the opposite effect. Though maybe there's something about parallel's deadlocks I'm missing.
I think you're good since the problem is older than your pr :D
Oh good! I mean bad, but I was dreading a very long debugging session
well, if you feel bored or something.... :upsidedownface:
Serial rustc creates a single thread called rustc. I assume parallel rustc just doesn't name its rayon threads, no debugging session ahead.
We create a new thread to look for query cycles, it's unnamed at the moment and that's where the panic happens.

Discussion:
threads: usize, f: F, ) -> R { <del> use rustc_data_structures::{jobserver, sync::FromDyn}; </del> <ins> use rustc_data_structures::{defer, jobserver, sync::FromDyn}; </ins> use rustc_middle::ty::tls; use rustc_query_impl::QueryCtxt; <del> use rustc_query_system::query::{deadlock, QueryContext}; </del> <ins> use rustc_query_system::query::{break_query_cycles, QueryContext}; use std::process; </ins> let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap());

let query_map = FromDyn::from(tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs())); let registry = rayon_core::Registry::current(); <del> thread::spawn(move || deadlock(query_map.into_inner(), &registry)); </del> <ins> 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(), &registry); on_panic.disable(); }) .unwrap(); </ins> }); if let Some(size) = get_stack_size() { builder = builder.stack_size(size);

use { parking_lot::{Condvar, Mutex}, rustc_data_structures::fx::FxHashSet, <del> rustc_data_structures::{defer, jobserver}, </del> <ins> rustc_data_structures::jobserver, </ins> rustc_span::DUMMY_SP, std::iter, <del> std::process, </del> std::sync::Arc, };

/// 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)] <del> pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { let on_panic = defer(|| { eprintln!("deadlock handler panicked, aborting process"); process::abort(); }); </del> <ins> pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) { </ins> let mut wakelist = Vec::new(); let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect();

// 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 { <del> if query_map.len() == 0 { panic!("deadlock detected without any query!") } else { panic!("deadlock detected! current query map:n{:#?}", query_map); } </del> <ins> panic!( "deadlock detected as we're unable to find a query cycle to breakn current query map:n{:#?}", query_map ); </ins> } // FIXME: Ensure this won't cause a deadlock before we return for waiter in wakelist.into_iter() { waiter.notify(registry); } <del> on_panic.disable(); </del> } #[inline(never)]

mod job; #[cfg(parallel_compiler)] <del> pub use self::job::deadlock; </del> <ins> pub use self::job::break_query_cycles; </ins> pub use self::job::{ print_query_stack, report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap, };