From: Ludovic Henry Date: Thu, 16 Feb 2017 01:46:26 +0000 (-0500) Subject: [socket] Fix race on SocketAsyncResult (#4389) X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=commitdiff_plain;h=5f7e9663af62fd54f4824289d3b86052a62aa008 [socket] Fix race on SocketAsyncResult (#4389) It might be possible that the callback modifies the current SocketAsyncResult via the Init method. We observe it with AcceptAsync with a ReceiveAsync in the callback. --- diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs index c63b1781660..2533129e7e5 100644 --- a/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs @@ -145,22 +145,33 @@ namespace System.Net.Sockets IsCompleted = true; + /* It is possible that this.socket is modified by this.Init which has been called by the callback. This + * would lead to inconsistency, as we would for example not release the correct socket.ReadSem or + * socket.WriteSem. + * For example, this can happen with AcceptAsync followed by a ReceiveAsync on the same + * SocketAsyncEventArgs */ + Socket completedSocket = socket; + SocketOperation completedOperation = operation; + AsyncCallback callback = AsyncCallback; if (callback != null) { ThreadPool.UnsafeQueueUserWorkItem (_ => callback (this), null); } - switch (operation) { + /* Warning: any field on the current SocketAsyncResult might have changed, as the callback might have + * called this.Init */ + + switch (completedOperation) { case SocketOperation.Receive: case SocketOperation.ReceiveFrom: case SocketOperation.ReceiveGeneric: case SocketOperation.Accept: - socket.ReadSem.Release (); + completedSocket.ReadSem.Release (); break; case SocketOperation.Send: case SocketOperation.SendTo: case SocketOperation.SendGeneric: - socket.WriteSem.Release (); + completedSocket.WriteSem.Release (); break; }