From: Greg Young Date: Wed, 2 Mar 2016 21:28:49 +0000 (+0200) Subject: handles AwaitAsync finishing synchronously X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=123aaa5db07fe464d12ea178ecc3f27990cc1a72;p=mono.git handles AwaitAsync finishing synchronously A connect flood will break the async loop and take down the entire HttpListener instance (will stop accepting connections). To reproduce. Take a HttpListener run say 2 wrk test instances against it (1000 connections each works here). After the run the HttpListener has broken its async loop and will no longer accept any connections after. The reason for this is that it was not previously handling the case that AcceptAsync can return synchronously. In this case event will not be called with args. Patch handles this case and the above issue is not reproducible with. --- diff --git a/mcs/class/System/System.Net/EndPointListener.cs b/mcs/class/System/System.Net/EndPointListener.cs index 9726b91358b..5400d73b87e 100644 --- a/mcs/class/System/System.Net/EndPointListener.cs +++ b/mcs/class/System/System.Net/EndPointListener.cs @@ -73,7 +73,7 @@ namespace System.Net { SocketAsyncEventArgs args = new SocketAsyncEventArgs (); args.UserToken = this; args.Completed += OnAccept; - sock.AcceptAsync (args); + Accept (sock, args); prefixes = new Hashtable (); unregistered = new Dictionary (); } @@ -82,28 +82,25 @@ namespace System.Net { get { return listener; } } - static void OnAccept (object sender, EventArgs e) + static void Accept (Socket socket, SocketAsyncEventArgs e) { + e.AcceptSocket = null; + var asyn = socket.AcceptAsync(e); + if (!asyn) { + ProcessAccept(e); + } + } + + + static void ProcessAccept (SocketAsyncEventArgs args) { - SocketAsyncEventArgs args = (SocketAsyncEventArgs) e; - EndPointListener epl = (EndPointListener) args.UserToken; Socket accepted = null; - if (args.SocketError == SocketError.Success) { + if (args.SocketError == SocketError.Success) accepted = args.AcceptSocket; - args.AcceptSocket = null; - } - try { - if (epl.sock != null) - epl.sock.AcceptAsync (args); - } catch { - if (accepted != null) { - try { - accepted.Close (); - } catch {} - accepted = null; - } - } + EndPointListener epl = (EndPointListener) args.UserToken; + + Accept (epl.sock, args); if (accepted == null) return; @@ -118,7 +115,12 @@ namespace System.Net { conn.BeginReadRequest (); } - internal void RemoveConnection (HttpConnection conn) + static void OnAccept (object sender, SocketAsyncEventArgs e) + { + ProcessAccept (e); + } + + internal void RemoveConnection (HttpConnection conn) { lock (unregistered) { unregistered.Remove (conn);