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

FileStream Not Suppressing Finalization on Dispose Call #108465

Open
StasPerekrestov opened this issue Oct 2, 2024 · 2 comments
Open

FileStream Not Suppressing Finalization on Dispose Call #108465

StasPerekrestov opened this issue Oct 2, 2024 · 2 comments
Labels
area-System.IO untriaged New issue has not been triaged by the area owner

Comments

@StasPerekrestov
Copy link

Description

Hello,
I’ve been monitoring my app running in a Docker container and recently examined its memory dump.
One thing that stood out was the presence of FileStream instances in the Finalization Queue.
image

These instances are created by the OpenTelemetry.Instrumentation.Process library, which I use to gather metrics.
On Linux, the library reads from the /proc/self/status file pretty often, using FileStream for this task(via System.Diagnostics.Process), and it appears to dispose of the streams correctly.

However, during my investigation, I noticed something interesting about the FileStream class.
When Dispose is called, FileStream does not suppress finalization, meaning it remains in the Finalization Queue.
In contrast, calling DisposeAsync does suppress finalization.

        // _strategy can be null only when ctor has thrown
        protected override void Dispose(bool disposing) => _strategy?.DisposeInternal(disposing);

        public override async ValueTask DisposeAsync()
        {
            await _strategy.DisposeAsync().ConfigureAwait(false);

            // For compatibility, derived classes must only call base.DisposeAsync(),
            // otherwise we would end up calling Dispose twice (one from base.DisposeAsync() and one from here).
            if (!_strategy.IsDerived)
            {
                Dispose(false);
                GC.SuppressFinalize(this);
            }
        }

Is this behavior intentional, or is there an opportunity for improvement in the Dispose implementation to align it with DisposeAsync?

Thank you in advance.

Reproduction Steps

  1. Open a file and obtain a FileStream instance.
  2. Call Dispose on the FileStream instance.
  3. Inspect the Finalization Queue to verify if the FileStream remains in it.

Expected behavior

The FileStream shouldn't appear in the Finalization Queue

Actual behavior

The FileStream gets into the Finalization Queue

Regression?

Related task #80439

Known Workarounds

No response

Configuration

No response

Other information

No response

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Oct 2, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

@stephentoub
Copy link
Member

cc: @adamsitnik

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.IO untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

2 participants