From cbe034b55fff4ad57b2f0f2198e4c469290323c2 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 13 Feb 2020 17:44:07 -0800 Subject: [PATCH] Remove lock allocation from SafeSocketHandle on Windows 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. --- .../src/System/Net/Sockets/SafeSocketHandle.Windows.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Windows.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Windows.cs index 30340947d126bd..11c4ad6159b58c 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Windows.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SafeSocketHandle.Windows.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Win32.SafeHandles; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; @@ -13,7 +12,6 @@ public partial class SafeSocketHandle { private ThreadPoolBoundHandle _iocpBoundHandle; private bool _skipCompletionPortOnSuccess; - private readonly object _iocpBindingLock = new object(); internal void SetExposed() { /* nop */ } @@ -40,7 +38,7 @@ internal ThreadPoolBoundHandle GetOrAllocateThreadPoolBoundHandle(bool trySkipCo return _iocpBoundHandle; } - lock (_iocpBindingLock) + lock (this) { ThreadPoolBoundHandle boundHandle = _iocpBoundHandle;