https reused socket bug, caused spurious OutOfMemoryError from phobos!

This commit is contained in:
Adam D. Ruppe 2017-02-22 12:29:21 -05:00
parent 2fff81a252
commit 5ff256380a
1 changed files with 10 additions and 6 deletions

16
http2.d
View File

@ -283,9 +283,9 @@ class HttpRequest {
// The key is the *domain name* and the port. Multiple domains on the same address will have separate connections. // The key is the *domain name* and the port. Multiple domains on the same address will have separate connections.
Socket[][string] socketsPerHost; Socket[][string] socketsPerHost;
void loseSocket(string host, ushort port, Socket s) { void loseSocket(string host, ushort port, bool ssl, Socket s) {
import std.string; import std.string;
auto key = format("%s:%s", host, port); auto key = format("http%s://%s:%s", ssl ? "s" : "", host, port);
if(auto list = key in socketsPerHost) { if(auto list = key in socketsPerHost) {
for(int a = 0; a < (*list).length; a++) { for(int a = 0; a < (*list).length; a++) {
@ -293,7 +293,7 @@ class HttpRequest {
for(int b = a; b < (*list).length - 1; b++) for(int b = a; b < (*list).length - 1; b++)
(*list)[b] = (*list)[b+1]; (*list)[b] = (*list)[b+1];
(*list).length = (*list).length - 1; (*list) = (*list)[0 .. $-1];
break; break;
} }
} }
@ -310,6 +310,7 @@ class HttpRequest {
socket.connect(new InternetAddress(host, port)); socket.connect(new InternetAddress(host, port));
debug(arsd_http2) writeln("opening to ", host, ":", port); debug(arsd_http2) writeln("opening to ", host, ":", port);
assert(socket.handle() !is socket_t.init);
return socket; return socket;
} }
@ -323,8 +324,11 @@ class HttpRequest {
// let's see if it has closed since we last tried // let's see if it has closed since we last tried
// e.g. a server timeout or something. If so, we need // e.g. a server timeout or something. If so, we need
// to lose this one and immediately open a new one. // to lose this one and immediately open a new one.
SocketSet readSet = new SocketSet(); static SocketSet readSet = null;
if(readSet is null)
readSet = new SocketSet();
readSet.reset(); readSet.reset();
assert(socket.handle() !is socket_t.init, socket is null ? "null" : socket.toString());
readSet.add(socket); readSet.add(socket);
auto got = Socket.select(readSet, null, null, 5.msecs /* timeout */); auto got = Socket.select(readSet, null, null, 5.msecs /* timeout */);
if(got > 0) { if(got > 0) {
@ -332,7 +336,7 @@ class HttpRequest {
// any active requests. Assume it is EOF and open a new one // any active requests. Assume it is EOF and open a new one
socket.close(); socket.close();
loseSocket(host, port, socket); loseSocket(host, port, ssl, socket);
goto openNew; goto openNew;
} }
return socket; return socket;
@ -432,7 +436,7 @@ class HttpRequest {
debug(arsd_http2) writeln("remote disconnect"); debug(arsd_http2) writeln("remote disconnect");
request.state = State.aborted; request.state = State.aborted;
inactive[inactiveCount++] = sock; inactive[inactiveCount++] = sock;
loseSocket(request.requestParameters.host, request.requestParameters.port, sock); loseSocket(request.requestParameters.host, request.requestParameters.port, request.requestParameters.ssl, sock);
} else { } else {
// data available // data available
request.handleIncomingData(buffer[0 .. got]); request.handleIncomingData(buffer[0 .. got]);