Skip to content

run_with_progress can livelock on closed progress channel #71

@ndenev

Description

@ndenev

Summary

run_with_progress can livelock when the broadcast progress channel is closed.

Affected code

  • src/progress.rs (run_with_progress)

Root cause

run_with_progress uses:

  • tokio::select! { biased; ... }
  • one branch awaiting progress_rx.recv()
  • one branch awaiting the main future

When the sender side drops, progress_rx.recv() returns Err(Closed) immediately and keeps being ready forever. With biased;, that branch is always preferred, and because closed errors are ignored, the loop can spin and starve completion.

Impact

  • Potential hang during interactive startup/context switch operations using run_with_progress.
  • Potential CPU spin in closed-channel edge cases.

Proposed fix

  1. Handle recv errors explicitly:
    • Err(RecvError::Closed): disable progress polling (or break) and await the main future directly.
    • Err(RecvError::Lagged(_)): continue.
  2. Optionally remove biased; to reduce starvation risk, but explicit Closed handling is still required.

Tests to add

  1. Closed receiver + pending future: function should still return when future completes (no hang).
  2. Lagged updates do not abort operation.
  3. Regression test with timeout to guard against infinite loop.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions