Fix multiple async accepts
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Thu, 8 Mar 2012 19:30:04 +0000 (14:30 -0500)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Thu, 8 Mar 2012 19:32:49 +0000 (14:32 -0500)
Running multiple BeginAccepts or AcceptAsync at the same time on the
same socket requires serialization.
Fixes bug #3805.

mcs/class/System/System.Net.Sockets/Socket.cs
mcs/class/System/System.Net.Sockets/Socket_2_1.cs

index 53ed16251f97221b2153653d6d9fd1917bf0dcc8..ea25e8c5c16bcf52876cbc88373a06a446765ee6 100644 (file)
@@ -523,7 +523,13 @@ namespace System.Net.Sockets
                        e.curSocket = this;
                        Worker w = e.Worker;
                        w.Init (this, e, SocketOperation.Accept);
-                       socket_pool_queue (Worker.Dispatcher, w.result);
+                       int count;
+                       lock (readQ) {
+                               readQ.Enqueue (e.Worker);
+                               count = readQ.Count;
+                       }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, w.result);
                        return true;
                }
 #endif
@@ -605,7 +611,13 @@ namespace System.Net.Sockets
                                throw new InvalidOperationException ();
 
                        SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
-                       socket_pool_queue (Worker.Dispatcher, req);
+                       int count;
+                       lock (readQ) {
+                               readQ.Enqueue (req.Worker);
+                               count = readQ.Count;
+                       }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
                        return req;
                }
 
@@ -624,7 +636,13 @@ namespace System.Net.Sockets
                        req.Offset = 0;
                        req.Size = receiveSize;
                        req.SockFlags = SocketFlags.None;
-                       socket_pool_queue (Worker.Dispatcher, req);
+                       int count;
+                       lock (readQ) {
+                               readQ.Enqueue (req.Worker);
+                               count = readQ.Count;
+                       }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
                        return req;
                }
 
@@ -661,7 +679,13 @@ namespace System.Net.Sockets
                        req.Size = receiveSize;
                        req.SockFlags = SocketFlags.None;
                        req.AcceptSocket = acceptSocket;
-                       socket_pool_queue (Worker.Dispatcher, req);
+                       int count;
+                       lock (readQ) {
+                               readQ.Enqueue (req.Worker);
+                               count = readQ.Count;
+                       }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
                        return(req);
                }
 
index 0c0bbbaa0d8835c1451d39d5d60a04484a013c9b..77c8a42e2291ea3ee0f955cad34ccecde041dc00 100644 (file)
@@ -249,7 +249,8 @@ namespace System.Net.Sockets {
                                Queue queue = null;
                                if (operation == SocketOperation.Receive ||
                                    operation == SocketOperation.ReceiveFrom ||
-                                   operation == SocketOperation.ReceiveGeneric) {
+                                   operation == SocketOperation.ReceiveGeneric ||
+                                   operation == SocketOperation.Accept) {
                                        queue = Sock.readQ;
                                } else if (operation == SocketOperation.Send ||
                                           operation == SocketOperation.SendTo ||
@@ -262,7 +263,7 @@ namespace System.Net.Sockets {
                                        Worker worker = null;
                                        SocketAsyncCall sac = null;
                                        lock (queue) {
-                                               // queue.Count will only be 0 if the socket is closed while receive/send
+                                               // queue.Count will only be 0 if the socket is closed while receive/send/accept
                                                // operation(s) are pending and at least one call to this method is
                                                // waiting on the lock while another one calls CompleteAllOnDispose()
                                                if (queue.Count > 0)