From 123aaa5db07fe464d12ea178ecc3f27990cc1a72 Mon Sep 17 00:00:00 2001 From: Greg Young Date: Wed, 2 Mar 2016 23:28:49 +0200 Subject: [PATCH] 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. --- .../System/System.Net/EndPointListener.cs | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) 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); -- 2.25.1