Avoid internal exception on timeout of AsyncSemaphore request that races with disposal #924
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The repro is a very particularly timed race between a timer thread and disposal on another thread. As such, no test can reliably repro it except with careful scheduling under a debugger.
The scenario
AsyncSemaphore
that includes a timeout.CancellationHandler
is invoked. TheWaiterInfo.Trigger.TrySetCanceled
call succeeds. This thread is now suspended, before it enters the lock onAsyncSemaphore.syncObject
.AsyncSemaphore.Dispose()
, which runs to completion.WaiterInfo.Node
from theLinkedList
, but theLinkedList
was already cleared inDispose
, so an exception is thrown.The fix is simply to clear the
WaiterInfo.Node
property when that node no longer belongs to it. This causes the racingCancellationHandler
to skip the code to remove and recycle the node.Fixes #906