Skip to content

Possible CancellationTokenRegistration leak in AsyncOperation<T> #761

Closed
@invidious9000

Description

@invidious9000

Under profiling it appears as if BoundedChannel may leak cancellation callbacks when used in this manner:

var channel = Channel.CreateBounded<bool>(1);
while (true)
{
    using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100));
    try
    {
        await channel.Reader.ReadAsync(cts.Token);
    }
    catch (OperationCanceledException)
    {
    }
}

Firstly, is this an intended use case? We have a long-running Channel that multiple readers may attempt to read from (these readers may timeout and cancel their CancellationToken as they disconnect, the 100ms timeout with CTS is to simulate this faster).

If this is an intended use case it looks like _registration in AsyncOperation ctor is not disposed when cancellation path is taken? I see that TrySetResult() and TrySetException() both call UnregisterCancellation() but not TrySetCanceled(), though I am unsure if my understanding of this is correct.

In addition to this (or perhaps as a result of it) it seems like OperationCanceledExceptions are accumulated via ExceptionDispatchInfo and a reference back to Deque.

image

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions