Skip to content

SemaphoreSlim memory leak #120767

@alexclarkmusa

Description

@alexclarkmusa

Description

Performing a simple loop & wait while asynchronously awaiting either a SemaphoreSlim event or a task (via Task.WhenAny) seems to cause an ongoing increase in the number of "SemaphoreSlim+TaskNode" instances on the heap when examined via the Managed Memory snapshot (Visual Studio Diagnostic Tools).

Sample code shows a fairly common example of a service that might be watching ~100 different resources, polling every 5 seconds for new data/files/events. It either waits for its configured polling interval (hardcoded here to 5 seconds) OR until the SemaphoreSlim gets released (an interrupt).

Reproduction Steps


internal class Program
{
    private static readonly SemaphoreSlim _interrupter = new(0, 1);
    private static readonly CancellationToken _cancellationToken = CancellationToken.None;

    static async Task Main()
    {
        var procs = Enumerable.Range(1, 100).Select(i => Process()).ToList();
        await Task.WhenAll(procs);
    }

    private static async Task Process()
    {
        while (true)
        {
            await Interruption(TimeSpan.FromMilliseconds(5000));
            // look for new data here
        }
    }

    private static async Task Interruption(TimeSpan delay)
    {
        var delayTask = Task.Delay(delay, _cancellationToken);
        var interruptTask = _interrupter.WaitAsync(_cancellationToken);

        // Wait until either the delay has expired or we got interrupted
        await Task.WhenAny(interruptTask, delayTask);
    }
}

Expected behavior

That the GC would collect these instances. In the code, it is not obvious/intuitive at all that this would result in a memory leak.

Actual behavior

After 5s runtime:
Image

After 30s:
Image

After 60s: (comparing to first snapshot)
Image

After 5 mins runtime: (comparing to first snapshot)
Image

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-System.ThreadingquestionAnswer questions and provide assistance, not an issue with source code or documentation.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions