ParallelLimitHandler.AcquireParallelLimitAsync/AcquireExecutionTypeLimitAsync call WaitAsync() with no cancellation token, and they run after scheduler.MarkModuleStarted has already transitioned the module to Executing and recorded start metrics (ModuleRunner.cs:134 vs 586-587).
Consequences: (1) during fail-fast shutdown a module blocked on a limiter slot cannot be interrupted — it waits until a slot frees, which never happens if the holder ignores its token and no timeout is configured, hanging the worker pool drain; (2) time spent queued behind the limiter is attributed to execution in metrics/concurrency snapshots and in the scheduler's constraint evaluation, which sees a "running" module that hasn't started.
Fix: pass the worker/engine cancellation token into both WaitAsync calls and consider acquiring the limits before MarkModuleStarted (or recording a separate "slot wait" phase) so state and telemetry reflect reality.
Evidence: src/ModularPipelines/Engine/Execution/ParallelLimitHandler.cs:39,57, src/ModularPipelines/Engine/Execution/ModuleRunner.cs:134,586-587
Raised by the v4 scoping audit round 3 — umbrella #3239.
ParallelLimitHandler.AcquireParallelLimitAsync/AcquireExecutionTypeLimitAsynccallWaitAsync()with no cancellation token, and they run afterscheduler.MarkModuleStartedhas already transitioned the module to Executing and recorded start metrics (ModuleRunner.cs:134vs586-587).Consequences: (1) during fail-fast shutdown a module blocked on a limiter slot cannot be interrupted — it waits until a slot frees, which never happens if the holder ignores its token and no timeout is configured, hanging the worker pool drain; (2) time spent queued behind the limiter is attributed to execution in metrics/concurrency snapshots and in the scheduler's constraint evaluation, which sees a "running" module that hasn't started.
Fix: pass the worker/engine cancellation token into both
WaitAsynccalls and consider acquiring the limits beforeMarkModuleStarted(or recording a separate "slot wait" phase) so state and telemetry reflect reality.Evidence:
src/ModularPipelines/Engine/Execution/ParallelLimitHandler.cs:39,57,src/ModularPipelines/Engine/Execution/ModuleRunner.cs:134,586-587Raised by the v4 scoping audit round 3 — umbrella #3239.