Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 17ce587

Browse files
committed
Stop disposing previous managed HttpListener connection on accept failure
The managed implementation of HttpListener launches an asynchronous accept loop: each accept spawns the next async accept. If an async accept fails, for some reason the current code is actually closing the previously accepted connection, which doesn't make sense. Stop doing that.
1 parent 153de68 commit 17ce587

File tree

1 file changed

+19
-25
lines changed

1 file changed

+19
-25
lines changed

src/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointListener.cs

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ namespace System.Net
3838
{
3939
internal sealed class HttpEndPointListener
4040
{
41-
private HttpListener _listener;
42-
private IPEndPoint _endpoint;
43-
private Socket _socket;
41+
private readonly HttpListener _listener;
42+
private readonly IPEndPoint _endpoint;
43+
private readonly Socket _socket;
44+
private readonly Dictionary<HttpConnection, HttpConnection> _unregisteredConnections;
4445
private Dictionary<ListenerPrefix, HttpListener> _prefixes;
4546
private List<ListenerPrefix> _unhandledPrefixes; // host = '*'
4647
private List<ListenerPrefix> _allPrefixes; // host = '+'
4748
private X509Certificate _cert;
4849
private bool _secure;
49-
private Dictionary<HttpConnection, HttpConnection> _unregisteredConnections;
5050

5151
public HttpEndPointListener(HttpListener listener, IPAddress addr, int port, bool secure)
5252
{
@@ -62,11 +62,12 @@ public HttpEndPointListener(HttpListener listener, IPAddress addr, int port, boo
6262
_socket = new Socket(addr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
6363
_socket.Bind(_endpoint);
6464
_socket.Listen(500);
65+
6566
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
6667
args.UserToken = this;
6768
args.Completed += OnAccept;
68-
Socket dummy = null;
69-
Accept(_socket, args, ref dummy);
69+
Accept(args);
70+
7071
_prefixes = new Dictionary<ListenerPrefix, HttpListener>();
7172
_unregisteredConnections = new Dictionary<HttpConnection, HttpConnection>();
7273
}
@@ -76,27 +77,21 @@ internal HttpListener Listener
7677
get { return _listener; }
7778
}
7879

79-
private static void Accept(Socket socket, SocketAsyncEventArgs e, ref Socket accepted)
80+
private void Accept(SocketAsyncEventArgs e)
8081
{
8182
e.AcceptSocket = null;
8283
bool asyn;
8384
try
8485
{
85-
asyn = socket.AcceptAsync(e);
86+
asyn = _socket.AcceptAsync(e);
8687
}
87-
catch
88+
catch (ObjectDisposedException)
8889
{
89-
if (accepted != null)
90-
{
91-
try
92-
{
93-
accepted.Close();
94-
}
95-
catch
96-
{
97-
}
98-
accepted = null;
99-
}
90+
// Once the listener starts running, it kicks off an async accept,
91+
// and each subsequent accept initiates the next async accept. At
92+
// point if the listener is torn down, the socket will be disposed
93+
// and the AcceptAsync on the socket can fail with an ODE. Far from
94+
// ideal, but for now just eat such exceptions.
10095
return;
10196
}
10297
if (!asyn)
@@ -107,13 +102,11 @@ private static void Accept(Socket socket, SocketAsyncEventArgs e, ref Socket acc
107102

108103
private static void ProcessAccept(SocketAsyncEventArgs args)
109104
{
110-
Socket accepted = null;
111-
if (args.SocketError == SocketError.Success)
112-
accepted = args.AcceptSocket;
113-
114105
HttpEndPointListener epl = (HttpEndPointListener)args.UserToken;
115106

116-
Accept(epl._socket, args, ref accepted);
107+
Socket accepted = args.SocketError == SocketError.Success ? args.AcceptSocket : null;
108+
epl.Accept(args);
109+
117110
if (accepted == null)
118111
return;
119112

@@ -122,6 +115,7 @@ private static void ProcessAccept(SocketAsyncEventArgs args)
122115
accepted.Close();
123116
return;
124117
}
118+
125119
HttpConnection conn = new HttpConnection(accepted, epl, epl._secure, epl._cert);
126120
lock (epl._unregisteredConnections)
127121
{

0 commit comments

Comments
 (0)