AsyncSemaphore fix for deadlock in narrow cancellation race condition #1001
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.
This avoids calling
CancellationTokenRegistration.Dispose
while holding a private lock in EnterAsync. There is one remaining case where we may hold a lock while calling it, but that's in the inlined case of EnterAsync and CTR will have its default value, and thus could not have anything to block on.The problematic case that we're fixing is when the token is canceled while EnterAsync is executing between where the CTR is assigned and where we called
info.Cleanup()
. In such a case, we would deadlock because Cleanup would wait for handlers to complete but the handler is waiting for the lock.There is no unit test change as part of this because the race condition is so very narrow that we couldn't write a unit test that would reliably hit it. However, I did temporarily make a code change that would throw when we held a lock in the evil case and our stress test did hit it before the fix and did not hit it after the fix, so I feel with that manual testing that we likely resolved the issue.
Fixes #1000