Found in the pre-4.0 audit (follow-up to #360/#361).
ProcessorLifecycle.CancelAll checks _disposed without the dispose lock, then CancelAllCore calls _cancellationTokenSource.Cancel(). A concurrent Dispose() can pass its own flag check and dispose the CTS inside that window, so the external CancelAll() caller gets ObjectDisposedException.
The README promises "all disposal operations are thread-safe", and ResultAsyncEnumerableParallelProcessor.CancelForDisposal already handles this exact race by catching ObjectDisposedException — the lifecycle should match.
Fix: catch ObjectDisposedException around the Cancel() call in CancelAllCore (still complete the per-item completion sources as canceled), mirroring the streaming processor.
Found in the pre-4.0 audit (follow-up to #360/#361).
ProcessorLifecycle.CancelAllchecks_disposedwithout the dispose lock, thenCancelAllCorecalls_cancellationTokenSource.Cancel(). A concurrentDispose()can pass its own flag check and dispose the CTS inside that window, so the externalCancelAll()caller getsObjectDisposedException.The README promises "all disposal operations are thread-safe", and
ResultAsyncEnumerableParallelProcessor.CancelForDisposalalready handles this exact race by catchingObjectDisposedException— the lifecycle should match.Fix: catch
ObjectDisposedExceptionaround theCancel()call inCancelAllCore(still complete the per-item completion sources as canceled), mirroring the streaming processor.