more relaibility under crappy connections

This commit is contained in:
Adam D. Ruppe 2017-04-26 22:20:32 -04:00
parent fcb59c4c55
commit c8c61150d5
1 changed files with 55 additions and 43 deletions

98
cgi.d
View File

@ -2649,56 +2649,64 @@ mixin template CustomCgiMainImpl(CustomCgi, alias fun, long maxContentLength = d
i = addr.sizeof; i = addr.sizeof;
int s = accept(sock, &addr, &i); int s = accept(sock, &addr, &i);
if(s == -1) try {
throw new Exception("accept");
//ubyte[__traits(classInstanceSize, BufferedInputRange)] bufferedRangeContainer;
auto ir = new BufferedInputRange(s);
//auto ir = emplace!BufferedInputRange(bufferedRangeContainer, s, backingBuffer);
while(!ir.empty) { if(s == -1)
ubyte[__traits(classInstanceSize, CustomCgi)] cgiContainer; throw new Exception("accept");
Cgi cgi; scope(failure) close(s);
try { //ubyte[__traits(classInstanceSize, BufferedInputRange)] bufferedRangeContainer;
cgi = new CustomCgi(ir, &closeConnection); auto ir = new BufferedInputRange(s);
//cgi = emplace!CustomCgi(cgiContainer, ir, &closeConnection); //auto ir = emplace!BufferedInputRange(bufferedRangeContainer, s, backingBuffer);
} catch(Throwable t) {
// a construction error is either bad code or bad request; bad request is what it should be since this is bug free :P
// anyway let's kill the connection
stderr.writeln(t.toString());
sendAll(ir.source, plainHttpError(false, "400 Bad Request", t));
closeConnection = true;
break;
}
assert(cgi !is null);
scope(exit)
cgi.dispose();
try { while(!ir.empty) {
fun(cgi); ubyte[__traits(classInstanceSize, CustomCgi)] cgiContainer;
cgi.close();
} catch(ConnectionException ce) { Cgi cgi;
closeConnection = true; try {
} catch(Throwable t) { cgi = new CustomCgi(ir, &closeConnection);
// a processing error can be recovered from //cgi = emplace!CustomCgi(cgiContainer, ir, &closeConnection);
stderr.writeln(t.toString); } catch(Throwable t) {
if(!handleException(cgi, t)) // a construction error is either bad code or bad request; bad request is what it should be since this is bug free :P
// anyway let's kill the connection
stderr.writeln(t.toString());
sendAll(ir.source, plainHttpError(false, "400 Bad Request", t));
closeConnection = true; closeConnection = true;
} break;
}
assert(cgi !is null);
scope(exit)
cgi.dispose();
if(closeConnection) { try {
ir.source.close(); fun(cgi);
break; cgi.close();
} else { } catch(ConnectionException ce) {
if(!ir.empty) closeConnection = true;
ir.popFront(); // get the next } catch(Throwable t) {
else if(ir.sourceClosed) { // a processing error can be recovered from
stderr.writeln(t.toString);
if(!handleException(cgi, t))
closeConnection = true;
}
if(closeConnection) {
ir.source.close(); ir.source.close();
break;
} else {
if(!ir.empty)
ir.popFront(); // get the next
else if(ir.sourceClosed) {
ir.source.close();
}
} }
} }
}
ir.source.close(); ir.source.close();
} catch(Throwable t) {
debug writeln(t);
// most likely cause is a timeout
}
} }
} else { } else {
processCount++; processCount++;
@ -3138,6 +3146,9 @@ class BufferedInputRange {
} }
this(Socket source, ubyte[] buffer = null) { this(Socket source, ubyte[] buffer = null) {
// if they connect but never send stuff to us, we don't want it wasting the process
// so setting a time out
source.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, dur!"seconds"(3));
this.source = source; this.source = source;
if(buffer is null) { if(buffer is null) {
underlyingBuffer = new ubyte[4096]; underlyingBuffer = new ubyte[4096];
@ -3194,10 +3205,11 @@ class BufferedInputRange {
if(ret == Socket.ERROR) { if(ret == Socket.ERROR) {
version(Posix) { version(Posix) {
import core.stdc.errno; import core.stdc.errno;
if(errno == EINTR) if(errno == EINTR) {
goto try_again; goto try_again;
}
} }
throw new Exception("uh oh " ~ lastSocketError); // FIXME throw new Exception(lastSocketError); // FIXME
} }
if(ret == 0) { if(ret == 0) {
sourceClosed = true; sourceClosed = true;