-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
SafeSocketHandle: avoid potential blocking of finalizer thread #41508
Conversation
When the Socket is Disposed, it attempts to make all on-going operations abort. It does this in a loop, and decides there are no on-going operations when the reference count becomes zero and the handle gets released. SafePipeHandle holds a reference to SafeSocketHandle. This prevents the reference count to drop to zero, and causes the dispose to loop infinitly. When the Socket is disposed from the finalizer thread, it is no longer used for operations and we can skip the loop. This avoids blocking the finalizer thread when the reference count can't drop to zero.
Tagging subscribers to this area: @dotnet/ncl |
I know it's a bit off-topic, but if we are already here, would make sense to remove comments about inner/outer handles in
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just nits, should be good once a test is added.
src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Windows.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.cs
Outdated
Show resolved
Hide resolved
Anton, thanks for reviewing! I've addressed your feedback. Socket tests pass on my machine. |
src/libraries/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs
Outdated
Show resolved
Hide resolved
The OSX test failure is unrelated and tracked in #41511, the mono one seems to be a hang in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
@geoffkizer if you are also fine with the changes and all tests do pass, maybe we can even do the packport today?
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Inner loop test failure is #41078 |
src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test failure seems related:
Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object
at System.Net.Sockets.Socket.Dispose(Boolean disposing) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs:line 4262
at System.Net.Sockets.Socket.Finalize() in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs:line 4367
[ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object
at System.Net.Sockets.Socket.Dispose(Boolean disposing) in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs:line 4262
at System.Net.Sockets.Socket.Finalize() in /_/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs:line 4367
src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
Outdated
Show resolved
Hide resolved
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
We do have a test somewhere that ensures that the socket handle is closed when the Socket gets finalized, right? This was the original problem that led us to adding logic to the Socket finalizer. We need to make sure we haven't broken that again. |
NonDisposedSocket_SafeHandlesCollected ? |
/backport to release/5.0 |
Started backporting to release/5.0: https://github.com/dotnet/runtime/actions/runs/234344348 |
/backport to release/5.0-rc2 |
Started backporting to release/5.0-rc2: https://github.com/dotnet/runtime/actions/runs/236412175 |
…izer thread (#41747) Backport of #41508 to release/5.0-rc2 * SafeSocketHandle: avoid potential blocking of finalizer thread When the Socket is Disposed, it attempts to make all on-going operations abort. It does this in a loop, and decides there are no on-going operations when the reference count becomes zero and the handle gets released. SafePipeHandle holds a reference to SafeSocketHandle. This prevents the reference count to drop to zero, and causes the dispose to loop infinitly. When the Socket is disposed from the finalizer thread, it is no longer used for operations and we can skip the loop. This avoids blocking the finalizer thread when the reference count can't drop to zero. * When disposing from finalizer, fall back to ReleaseHandle * Add test * PR feedback * Fix test * PR feedback * Refactor * Refactor * Log call to _handle.Dispose * Handle null handle Co-authored-by: Tom Deseyn <[email protected]>
When the Socket is Disposed, it attempts to make all on-going operations
abort. It does this in a loop, and decides there are no on-going operations
when the reference count becomes zero and the handle gets released.
SafePipeHandle holds a reference to SafeSocketHandle. This prevents the
reference count to drop to zero, and causes the dispose to loop infinitly.
When the Socket is disposed from the finalizer thread, it is no longer used
for operations and we can skip the loop. This avoids blocking the finalizer
thread when the reference count can't drop to zero.
Fixes #40301
@antonfirsov @geoffkizer ptal
cc @jaredpar