Skip to content

Commit

Permalink
[Http]: Fix a potential race condition in the WebConnectionGroup's co…
Browse files Browse the repository at this point in the history
…nnection list.

Remove the "ConnectionState" from the connection list before closing the connection,
this should avoid ServicePoint.SendRequest() ever crashing with a NullReferenceException
due to getting a null return value from WebConnectionGroup.GetConnection().
  • Loading branch information
Martin Baulig committed Jun 11, 2014
1 parent c02a31c commit b314414
Showing 1 changed file with 20 additions and 18 deletions.
38 changes: 20 additions & 18 deletions mcs/class/System/System.Net/WebConnectionGroup.cs
Expand Up @@ -70,14 +70,16 @@ public void Close ()
//TODO: abort requests or wait for them to finish
lock (sPoint) {
closing = true;
foreach (var cnc in connections) {
if (cnc.Connection == null)
continue;
cnc.Connection.Close (false);
cnc.Connection = null;
var iter = connections.First;
while (iter != null) {
var cnc = iter.Value.Connection;
var node = iter;
iter = iter.Next;

connections.Remove (node);
cnc.Close (false);
OnConnectionClosed ();
}
connections.Clear ();
}
}

Expand Down Expand Up @@ -120,7 +122,7 @@ static void PrepareSharingNtlm (WebConnection cnc, HttpWebRequest request)
ConnectionState FindIdleConnection ()
{
foreach (var cnc in connections) {
if (cnc.Busy || cnc.Connection == null)
if (cnc.Busy)
continue;

connections.Remove (cnc);
Expand All @@ -140,7 +142,7 @@ WebConnection CreateOrReuseConnection (HttpWebRequest request, out bool created)
return cnc.Connection;
}

if (sPoint.ConnectionLimit > connections.Count) {
if (sPoint.ConnectionLimit > connections.Count || connections.Count == 0) {
created = true;
cnc = new ConnectionState (this);
connections.AddFirst (cnc);
Expand Down Expand Up @@ -177,14 +179,11 @@ internal bool TryRecycle (TimeSpan maxIdleTime, ref DateTime idleSince)
}

int count = 0;
for (var node = connections.First; node != null; node = node.Next) {
var cnc = node.Value;

if (cnc.Connection == null) {
connections.Remove (node);
OnConnectionClosed ();
continue;
}
var iter = connections.First;
while (iter != null) {
var cnc = iter.Value;
var node = iter;
iter = iter.Next;

++count;
if (cnc.Busy)
Expand All @@ -205,7 +204,7 @@ internal bool TryRecycle (TimeSpan maxIdleTime, ref DateTime idleSince)
if (connectionsToClose == null)
connectionsToClose = new List<WebConnection> ();
connectionsToClose.Add (cnc.Connection);
cnc.Connection = null;
connections.Remove (node);
}

recycled = connections.Count == 0;
Expand All @@ -224,7 +223,10 @@ internal bool TryRecycle (TimeSpan maxIdleTime, ref DateTime idleSince)
}

class ConnectionState : IWebConnectionState {
public WebConnection Connection;
public WebConnection Connection {
get;
private set;
}

public WebConnectionGroup Group {
get;
Expand Down

0 comments on commit b314414

Please sign in to comment.