Skip to content

fix(consensusmanager): don't panic on spawn_blocking cancellation during shutdown (#949) - #1030

Open
atharaldsen wants to merge 1 commit into
kaspanet:masterfrom
atharaldsen:fix-session-spawn-blocking-cancel
Open

fix(consensusmanager): don't panic on spawn_blocking cancellation during shutdown (#949)#1030
atharaldsen wants to merge 1 commit into
kaspanet:masterfrom
atharaldsen:fix-session-spawn-blocking-cancel

Conversation

@atharaldsen

Copy link
Copy Markdown
Contributor

Closes #949.

ConsensusSessionOwned::spawn_blocking did spawn_blocking(...).await.unwrap(). When the Tokio runtime shuts down it cancels not-yet-started blocking tasks, so the join returns Err(JoinError::Cancelled) and .unwrap() panics a runtime worker thread mid-teardown. This is observed during graceful shutdown under slow I/O (e.g. flushing a large block backlog to an HDD), where the node crashes instead of exiting cleanly — confirmed by @D-Stacks on the issue.

Handle the join result explicitly:

  • Cancellation only happens during runtime shutdown and has no result to return, so park until the task is dropped as part of teardown instead of panicking.
  • A genuine panic inside the closure is still propagated via resume_unwind, preserving previous behavior (real bugs are not masked).

Testing

Adds unit tests covering all three paths — result returned, cancellation parks, closure panic propagates — using a local multi-thread runtime (no new deps). The original crash is an intermittent shutdown race that isn't reliably reproducible, so the tests drive each JoinError branch deterministically with tokio's own abort() / panic!().

…ing shutdown (kaspanet#949)

`ConsensusSessionOwned::spawn_blocking` did `spawn_blocking(...).await.unwrap()`.
When the Tokio runtime shuts down it cancels not-yet-started blocking tasks, so
the join returns `Err(JoinError::Cancelled)` and `.unwrap()` panics a
runtime-worker thread mid-teardown (observed during graceful shutdown under slow
I/O, e.g. flushing a large block backlog to an HDD).

Handle the join result explicitly:
- Cancellation only happens during runtime shutdown and has no result to return,
  so park until the task is dropped as part of teardown instead of panicking.
- A genuine panic inside the closure is still propagated via `resume_unwind`,
  preserving the previous behavior (we don't mask real bugs).

Adds unit tests covering all three paths (result returned, cancellation parks,
closure panic propagates) using a local multi-thread runtime — no extra deps.
atharaldsen added a commit to atharaldsen/rusty-kaspa that referenced this pull request May 31, 2026
…shutdown (kaspanet#1031)

Several `spawn_blocking(...).await.unwrap()` (and one `try_join_all(...).await.unwrap()`)
sites panic a runtime worker thread when the Tokio runtime cancels a not-yet-started
blocking task during shutdown (`Err(JoinError::Cancelled)`). This is the same class of
bug fixed for `consensusmanager::session` in kaspanet#1030 (issue kaspanet#949).

Add `kaspa_core::task::blocking::{join_blocking_or_park, join_result_or_park}`:
- on cancellation (runtime shutdown, no result to return) park until teardown drops the task;
- on a genuine closure panic, propagate via `resume_unwind` (preserving prior behavior).

Apply it to the remaining sites from kaspanet#1031:
- `mining::manager::MiningManagerProxy` mempool proxy methods (9 sites)
- `indexes::utxoindex::UtxoIndexProxy` methods (4 sites)
- `protocol/flows` IBD staging commit and consensus-reset
- `connectionmanager` dns_seed blocking call and `try_join_all`

The `ConsensusProxy::spawn_blocking` call sites (handled by kaspanet#1030) are intentionally left
untouched. `consensusmanager::session` retains its local helper from kaspanet#1030; consolidating it
onto this shared helper is left as a follow-up to avoid conflicting with kaspanet#1030 while in review.

Adds unit tests for the shared helper (result returned, cancellation parks, closure panic
propagates).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic during graceful shutdown: JoinError::Cancelled in session.rs

1 participant