recursive close big bug fix

This commit is contained in:
Adam D. Ruppe 2012-03-24 23:29:20 -04:00
parent e1e9fcdf3e
commit 10bfe54b29
1 changed files with 29 additions and 7 deletions

36
cgi.d
View File

@ -741,6 +741,7 @@ class Cgi {
immutable(ubyte)[] data; immutable(ubyte)[] data;
void rdo(const(ubyte)[] d) { void rdo(const(ubyte)[] d) {
assert(d.length < 120);
sendAll(ir.source, d); sendAll(ir.source, d);
} }
@ -1292,7 +1293,7 @@ class Cgi {
} }
/// Writes the data to the output, flushing headers if they have not yet been sent. /// Writes the data to the output, flushing headers if they have not yet been sent.
void write(const(void)[] t, bool isAll = false) { void write(const(void)[] t, bool isAll = false, bool maybeAutoClose = true) {
assert(!closed, "Output has already been closed"); assert(!closed, "Output has already been closed");
if(gzipResponse && acceptsGzip && isAll) { // FIXME: isAll really shouldn't be necessary if(gzipResponse && acceptsGzip && isAll) { // FIXME: isAll really shouldn't be necessary
@ -1328,8 +1329,9 @@ class Cgi {
} }
} }
if(isAll) if(maybeAutoClose && isAll)
close(); // if you say it is all, that means we're definitely done close(); // if you say it is all, that means we're definitely done
// maybeAutoClose can be false though to avoid this (important if you call from inside close()!
} }
void flush() { void flush() {
@ -1352,20 +1354,23 @@ class Cgi {
return; // don't double close return; // don't double close
if(!outputtedResponseData) if(!outputtedResponseData)
write(""); write("", false, false);
// writing auto buffered data // writing auto buffered data
if(requestMethod != RequestMethod.HEAD && autoBuffer) { if(requestMethod != RequestMethod.HEAD && autoBuffer) {
if(!nph) if(!nph)
stdout.rawWrite(outputBuffer); stdout.rawWrite(outputBuffer);
else else
write(outputBuffer, true); // tell it this is everything write(outputBuffer, true, false); // tell it this is everything
} }
// closing the last chunk... // closing the last chunk...
if(nph && rawDataOutput !is null && responseChunked) if(nph && rawDataOutput !is null && responseChunked)
rawDataOutput(cast(const(ubyte)[]) "0\r\n\r\n"); rawDataOutput(cast(const(ubyte)[]) "0\r\n\r\n");
if(flushDelegate)
flushDelegate();
closed = true; closed = true;
} }
@ -1737,7 +1742,17 @@ mixin template CustomCgiMain(CustomCgi, alias fun, T...) if(is(CustomCgi : Cgi))
connection.close(); connection.close();
} }
bool closeConnection; bool closeConnection;
/*
auto sn = connection;
ubyte[1024] b;
sn.receive(b);
sendAll(sn, "HTTP/1.0 200 OK\r\n");
sendAll(sn, "Content-Length:11\r\n\r\nHello world");
sn.close();
continue;
*/
auto ir = new BufferedInputRange(connection); auto ir = new BufferedInputRange(connection);
while(!ir.empty) { while(!ir.empty) {
Cgi cgi; Cgi cgi;
try { try {
@ -1758,6 +1773,7 @@ mixin template CustomCgiMain(CustomCgi, alias fun, T...) if(is(CustomCgi : Cgi))
cgi.close(); cgi.close();
} catch(Throwable t) { } catch(Throwable t) {
// a processing error can be recovered from // a processing error can be recovered from
stderr.writeln(t.toString);
if(!handleException(cgi, t)) if(!handleException(cgi, t))
closeConnection = true; closeConnection = true;
} }
@ -2117,7 +2133,6 @@ class BufferedInputRange {
do { do {
auto freeSpace = underlyingBuffer[underlyingBuffer.ptr - view.ptr + view.length .. $]; auto freeSpace = underlyingBuffer[underlyingBuffer.ptr - view.ptr + view.length .. $];
auto ret = source.receive(freeSpace); auto ret = source.receive(freeSpace);
if(ret == Socket.ERROR) if(ret == Socket.ERROR)
throw new Exception("uh oh"); // FIXME throw new Exception("uh oh"); // FIXME
@ -2195,10 +2210,16 @@ class ListeningConnectionManager {
Socket listener; Socket listener;
int opApply(CMT dg) { bool running;
void quit() {
running = false;
}
int opApply(scope CMT dg) {
running = true;
shared(int) loopBroken; shared(int) loopBroken;
while(!loopBroken) { while(!loopBroken && running) {
auto sn = listener.accept(); auto sn = listener.accept();
auto thread = new ConnectionThread(sn, &loopBroken, dg); auto thread = new ConnectionThread(sn, &loopBroken, dg);
thread.start(); thread.start();
@ -2217,6 +2238,7 @@ void sendAll(Socket s, const(void)[] data) {
amount = s.send(data); amount = s.send(data);
if(amount == Socket.ERROR) if(amount == Socket.ERROR)
throw new Exception("wtf in send"); throw new Exception("wtf in send");
assert(amount > 0);
data = data[amount .. $]; data = data[amount .. $];
} while(data.length); } while(data.length);
} }