From 9ae88709dbd3d3ed77e1a6ed3d3493ec14f991fc Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 17 Mar 2015 12:49:11 +0000 Subject: [PATCH] [System] Fixed SafeSocketHandle concurrency problem. When ReleaseHandle was called by RegisterForBlockingSyscall's DangerousRelease the current thread would be in blocking_threads but there would be no blocking system call to interrupt. --- mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs b/mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs index 2e8c51e71a5..d4c3904f0c6 100644 --- a/mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs +++ b/mcs/class/System/System.Net.Sockets/SafeSocketHandle.cs @@ -17,6 +17,8 @@ namespace System.Net.Sockets { List blocking_threads; + const int SOCKET_CLOSED = 10004; + const int ABORT_RETRIES = 10; static bool THROW_ON_ABORT_RETRIES = Environment.GetEnvironmentVariable("MONO_TESTS_IN_PROGRESS") == "yes"; @@ -67,6 +69,15 @@ namespace System.Net.Sockets { break; } + /* + * This method can be called by the DangerousRelease inside RegisterForBlockingSyscall + * When this happens blocking_threads contains the current thread. + * We can safely close the socket and throw SocketException in RegisterForBlockingSyscall + * before the blocking system call. + */ + if (blocking_threads.Count == 1 && blocking_threads[0] == Thread.CurrentThread) + break; + AbortRegisteredThreads (); // Sleep so other threads can resume Thread.Sleep (1); @@ -93,6 +104,10 @@ namespace System.Net.Sockets { } if (release) DangerousRelease (); + + // Handle can be closed by DangerousRelease + if (IsClosed) + throw new SocketException (SOCKET_CLOSED); } } -- 2.11.4.GIT