-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
add missing GC.SuppressFinalize(this) to FileStream.DisposeAsync #65899
Conversation
Tagging subscribers to this area: @dotnet/area-system-io Issue DetailsI was unable to repro #65835 locally for a few hours, but I believe that the it's caused by lack of Explanation: the default runtime/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs Lines 176 to 180 in 95f7f7a
which calls runtime/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs Lines 158 to 167 in 95f7f7a
In #65835 we can see that the buffer was actually written to disk twice. I guess (I was not able to repro it) that it's caused by a flush implemented for finalizer. I am not 100% sure because the finally block sets write position to 0: runtime/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs Lines 115 to 121 in 95f7f7a
So after runtime/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs Lines 125 to 130 in 95f7f7a
I've tried really hard to write a failing unit test, but I've failed. The reason for that is that all custom types deriving from
which does call the base impl and is bug free.
|
src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs
Outdated
Show resolved
Hide resolved
…eam.BaseDisposeAsync, as FileStream.DisposeAsync calls Dispose(false) now
I was unable to repro #65835 locally for a few hours, but I believe that the it's caused by lack of
GC.SuppressFinalize(this)
inFileStream.DisposeAsync
and my recent changes from #64997 have just exposed the problem by adding the finalizer toFileStream
itself.Explanation: the default
Stream.DisposeAsync
callsDispose
:runtime/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs
Lines 176 to 180 in 95f7f7a
which calls
Close
which callsGC.SuppressFinalize(this)
:runtime/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs
Lines 158 to 167 in 95f7f7a
FileStream
was overridingDisposeAsync
, but not callingGC.SuppressFinalize(this)
.runtime/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs
Line 500 in 95f7f7a
In #65835 we can see that the buffer was actually written to disk twice. I guess (I was not able to repro it) that it's caused by a flush implemented for finalizer. I am not 100% sure because the finally block sets write position to 0:
runtime/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs
Lines 115 to 121 in 95f7f7a
So after
DisposeAsync
the flushing should in theory see that there is nothing to flush. Moreover, it should also observe that the handle was already closed.runtime/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs
Lines 125 to 130 in 95f7f7a
I've tried really hard to write a failing unit test, but I've failed. The reason for that is that all custom types deriving from
FileStream
are callingBaseDisposeAsync
:runtime/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs
Line 579 in 95f7f7a
which does call the base impl and is bug free.