Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cancellation-related deadlock in BoundedChannel #33883

Merged
merged 1 commit into from
Mar 21, 2020

Conversation

stephentoub
Copy link
Member

If:

  • a BoundedChannel is opted-in to synchronous continuations via someone setting AllowSynchronousContinuations on its options when constructed, and
  • if a read operation is performed when there's no data available and with a cancelable cancellation token, and
  • if cancellation is requested concurrently with a write being performed that will satisfy that read...

then there's the potential for a deadlock. While holding a lock, the writer needs to unregister the cancellation for the reader's operation prior to trying to complete it, and needs to know that all cancellation-related work has quiesced before it proceeds to try to complete that reader. If the cancellation is currently in progress then, it waits for the cancellation callback to complete. However, if a synchronous continuation was used, then it's possible the user's synchronous continuation might call back into the bounded channel and perform an operation that might require taking that same lock. Deadlock.

The fix is to simply not try to use synchronous continuations with bounded channel when a cancelable token is employed.

Fixes #33858
cc: @tarekgh

If:
- a BoundedChannel is opted-in to synchronous continuations via someone setting AllowSynchronousContinuations on its options when constructed, and
- if a read operation is performed when there's no data available and with a cancelable cancellation token, and
- if cancellation is requested concurrently with a write being performed that will satisfy that read...

then there's the potential for a deadlock.  While holding a lock, the writer needs to unregister the cancellation for the reader's operation prior to trying to complete it, and needs to know that all cancellation-related work has quiesced before it proceeds to try to complete that reader.  If the cancellation is currently in progress then, it waits for the cancellation callback to complete.  However, if a synchronous continuation was used, then it's possible the user's synchronous continuation might call back into the bounded channel and perform an operation that might require taking that same lock.  Deadlock.

The fix is to simply not try to use synchronous continuations with bounded channel when a cancelable token is employed.
@stephentoub stephentoub reopened this Mar 21, 2020
@stephentoub stephentoub merged commit d7db838 into dotnet:master Mar 21, 2020
@stephentoub stephentoub deleted the boundedchanneldeadlock branch March 21, 2020 12:18
@ghost ghost locked as resolved and limited conversation to collaborators Dec 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deadlock in System.Threading.Channels.BoundChannelWriter.TryWrite
3 participants