Skip to content

System.Threading.Tasks.Dataflow.BufferBlock - Memory leak on OutputAvailableAsync #99564

@elpht

Description

@elpht

Description

After upgrading to System.Threading.Tasks.Dataflow 8.0.0 from 4.11.1 I started noticing memory leaks originated on hosted services that implement a producer/consumer pattern using BufferBlock. After a closer look at a couple of process dumps, I could see lots of callback registrations on cancellation tokens presumably from DataflowBlock.OutputAvailableAsync:

image

I've checked the source code of DataflowBlock.OutputAvailableAsync and found that, since version 8.0.0, the registration to the CancellationToken provided to OutputAvailableAsync is no longer disposed. Actually, the delegate s_handleCompletion, which was used in earlier versions for that purpose, is never invoked. I guess that this misbehaviour, together with my implementation, that uses long-lived cancellation tokens to read from the BufferBlock, is what causes that memory leak.

Reproduction Steps

Given a hosted service implementing producer/consumer pattern using a BufferBlock, using always the same CancellationTokenSource to provide the CancellationToken to OutputAvailableAsync, then, just feed the consumer. The more items are produced, the faster the memory leak will show up.

Expected behavior

No memory leak.

Actual behavior

Memory leak

Regression?

I did not notice that behaviour in System.Threading.Tasks.Dataflow 4.11.1

Known Workarounds

In my case, switching from BufferBlock<T> to Channel<T>, which is not affected by this issue, was my "workaround".

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions