mirror of https://github.com/adamdruppe/arsd.git
recursive close big bug fix
This commit is contained in:
parent
e1e9fcdf3e
commit
10bfe54b29
36
cgi.d
36
cgi.d
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue