Rollup merge of #138581 - Zoxc:abort-handler-if-locked, r=SparrowLii

Abort in deadlock handler if we fail to get a query map

Resolving query cycles requires the complete active query map, or it may miss query cycles. We did not check that the map is completely constructed before. If there is some error collecting the map, something has gone wrong already. This adds a check to abort/panic if we fail to construct the complete map.

This can help differentiate errors from the `deadlock detected` case if constructing query map has errors in practice.

An `Option` is not used for `collect_active_jobs` as the panic handler can still make use of a partial map.
This commit is contained in:
Matthias Krüger 2025-03-25 18:09:05 +01:00 committed by GitHub
commit 43297ffc22
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 43 additions and 12 deletions

View file

@ -588,7 +588,12 @@ pub fn print_query_stack<Qcx: QueryContext>(
// state if it was responsible for triggering the panic.
let mut count_printed = 0;
let mut count_total = 0;
let query_map = qcx.collect_active_jobs();
// Make use of a partial query map if we fail to take locks collecting active queries.
let query_map = match qcx.collect_active_jobs() {
Ok(query_map) => query_map,
Err(query_map) => query_map,
};
if let Some(ref mut file) = file {
let _ = writeln!(file, "\n\nquery stack during panic:");

View file

@ -86,7 +86,7 @@ pub trait QueryContext: HasDepContext {
/// Get the query information from the TLS context.
fn current_query_job(self) -> Option<QueryJobId>;
fn collect_active_jobs(self) -> QueryMap;
fn collect_active_jobs(self) -> Result<QueryMap, QueryMap>;
/// Load a side effect associated to the node in the previous session.
fn load_side_effect(

View file

@ -260,8 +260,11 @@ where
Q: QueryConfig<Qcx>,
Qcx: QueryContext,
{
let error =
try_execute.find_cycle_in_stack(qcx.collect_active_jobs(), &qcx.current_query_job(), span);
// Ensure there was no errors collecting all active jobs.
// We need the complete map to ensure we find a cycle to break.
let query_map = qcx.collect_active_jobs().expect("failed to collect active queries");
let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span);
(mk_cycle(query, qcx, error), None)
}