Remove lock allocation from SafeSocketHandle on Windows#32275
Merged
stephentoub merged 1 commit intodotnet:masterfrom Feb 14, 2020
Merged
Remove lock allocation from SafeSocketHandle on Windows#32275stephentoub merged 1 commit intodotnet:masterfrom
stephentoub merged 1 commit intodotnet:masterfrom
Conversation
The first time a Socket is used, we bind its handle to the ThreadPool for overlapped I/O. In order to avoid this happening on multiple threads concurrently if multiple threads concurrently race to perform this initialization, we take a lock. We currently allocate an object and store it for the lifetime of the Socket, purely to do this one-time synchronization, after which the object is useless. While in general we prefer not to lock on `this` (in order to avoid any issues that might occur from an external consumer also locking on the same object), the chances of someone locking on this object are slim to none, and even if they did, it wouldn't make any difference once the socket was already initialized, and even if the socket wasn't yet initialized, it would only be a one-time contention, without lock ordering concerns.
jkotas
approved these changes
Feb 14, 2020
src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Windows.cs
Show resolved
Hide resolved
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The first time a Socket is used, we bind its handle to the ThreadPool for overlapped I/O. In order to avoid this happening on multiple threads concurrently if multiple threads concurrently race to perform this initialization, we take a lock. We currently allocate an object and store it for the lifetime of the Socket, purely to do this one-time synchronization, after which the object is useless. While in general we prefer not to lock on
thison exposed objects (in order to avoid any issues that might occur from an external consumer also locking on the same object), the chances of someone locking on this object are slim to none, and even if they did, it wouldn't make any difference once the socket was already initialized, and even if the socket wasn't yet initialized, it would only be a one-time contention, without lock ordering concerns. (Completely degenerate code could take and never release a lock on a socket's SafeHandle prior to first use, and that would then block that Socket from operating, but such code could also cause problems by just closing the exposed handle, and the answer would be the same: don't do that.)On the same test as in #32271...
Before:

After:

(this still includes the allocations removed in #32271)
cc: @dotnet/ncl