Skip to content

Resource leak in IAsyncEnumerable client-side disposal: server not notified on normal enumeration completion #1386

@javasir

Description

@javasir

I have a RPC interface defined like:

IAsyncEnumerable<Response> GetStates(Request request, CancellationToken token = default);
and there is a property with type of IAsyncEnumerable<Operation> in request parameter.

Summary
The AsyncEnumeratorProxy in MessageFormatterEnumerableTracker.cs fails to notify the server to dispose of the enumerator when enumeration completes normally (all values consumed). This causes a resource leak on the server side where enumerators remain tracked in the generatorsByToken dictionary indefinitely.

Root Cause
In AsyncEnumeratorProxy.DisposeAsync() (line 452), the disposal notification is only sent when generatorReportsFinished is false:
if (!this.generatorReportsFinished)
{
await this.owner.jsonRpc.NotifyAsync(DisposeMethodName, this.nextOrDisposeArguments).ConfigureAwait(false);
}
However, when enumeration completes normally:
The server sets results.Finished = true (line 327)
The client receives this and sets this.generatorReportsFinished = true (line 497)
When the await foreach loop completes and DisposeAsync() is called, the condition at line 452 evaluates to false
No disposal notification is sent to the server

Impact
Memory leak: Server-side enumerators remain in generatorsByToken dictionary until connection dies
Resource leak: Any resources held by the server-side GeneratingEnumeratorTracker are not properly disposed
Accumulation: Each completed enumeration leaves behind leaked resources in long-running connections

Expected Behavior
The client should always notify the server when disposing an enumerator, regardless of whether generatorReportsFinished is true. The server needs this notification to:
Remove the enumerator from generatorsByToken dictionary
Call DisposeAsync() on the GeneratingEnumeratorTracker instance
Release any associated resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions