diff --git a/cgi.c b/cgi.c index 7e2cc8c..71ba52d 100644 --- a/cgi.c +++ b/cgi.c @@ -4,6 +4,14 @@ sigchld(int sig) while (waitpid(0, NULL, WNOHANG) > 0); } +void +sigalarm_cgi(int sig) +{ + /* send this out regardless of whether we've already sent a header, + * to maybe help with debugging */ + badrequest(504, "Gateway Timeout", "The CGI is being too slow."); +} + static void cgi_child(const char *relpath) { @@ -165,6 +173,7 @@ serve_cgi(char *relpath) keepalive = 0; alarm(CGI_TIMEOUT); + signal(SIGALRM, sigalarm_cgi); cgi_parent(cin[0], cout[1], 0); exit(0); diff --git a/eris.c b/eris.c index 434fcb2..1b38f10 100644 --- a/eris.c +++ b/eris.c @@ -98,6 +98,7 @@ char *path; int http_version; char *content_type; size_t content_length; +int header_sent; off_t range_start, range_end; time_t ims = 0; @@ -143,6 +144,7 @@ dolog(int code, off_t len) void header(unsigned int code, const char *httpcomment) { + header_sent = 1; printf("HTTP/1.%d %u %s\r\n", http_version, code, httpcomment); printf("Server: " FNORD "\r\n"); printf("Connection: %s\r\n", keepalive?"keep-alive":"close"); @@ -519,6 +521,7 @@ handle_request() range_end = 0; content_type = NULL; content_length = 0; + header_sent = 0; alarm(READTIMEOUT); @@ -746,6 +749,14 @@ handle_request() return; } +void +sigalarm(int sig) +{ + if (! header_sent) { + badrequest(408, "Request Timeout", "You are being too slow."); + } +} + int main(int argc, char *argv[], const char *const *envp) { @@ -756,6 +767,7 @@ main(int argc, char *argv[], const char *const *envp) setbuffer(stdout, stdout_buf, sizeof stdout_buf); signal(SIGPIPE, SIG_IGN); + signal(SIGALRM, sigalarm); get_ucspi_env(); while (1) { diff --git a/test.sh b/test.sh index d51c9d9..a57318d 100755 --- a/test.sh +++ b/test.sh @@ -124,7 +124,6 @@ title "Too many headers" printf '\r\n') | $HTTPD 2>/dev/null | grep -q 'HTTP/1.. 431 ' && pass || fail - H "If-Modified-Since" title "Has been modified" @@ -189,6 +188,15 @@ printf 'GET /a.cgi HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | d | grep -Eq '%S title "Large response" printf 'GET /mongo.cgi HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | grep -q james && pass || fail + + +H "Timeouts" + +title "Read timeout" +(sleep 2.1; echo) | $HTTPD 2>&1 | grep -c 'HTTP/1.. 408 \|.null. 408' | grep -q 2 && pass || fail + + + H "fnord bugs" # 1. Should return directory listing of /; instead segfaults