mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
Fix hung connection from consecutive requests
A client making quick consecutive requests with keep-alive, such as `ab` with `-k`, can cause the connection to become hung. This happens because of an optimization in `http_poll` function. When a connection state becomes `DONE`, `httpd_poll` recycles the connection and immediately calls `poll_recv_request`. However, it doesn't handle this resulting in the connection state becoming `DONE` again. If this occurs, the state stays in `DONE`, and the further calls to `httpd_poll` ignore the connection. Fix this by calling `poll_recv_request` in a loop until the state is no longer `DONE`.
This commit is contained in:
@ -2495,7 +2495,7 @@ static void httpd_poll(void) {
|
||||
LIST_FOREACH_SAFE(conn, &connlist, entries, next) {
|
||||
switch (conn->state) {
|
||||
case DONE:
|
||||
/* do nothing */
|
||||
/* do nothing, no connection should be left in this state */
|
||||
break;
|
||||
|
||||
case RECV_REQUEST:
|
||||
@ -2578,16 +2578,17 @@ static void httpd_poll(void) {
|
||||
}
|
||||
|
||||
/* Handling SEND_REPLY could have set the state to done. */
|
||||
if (conn->state == DONE) {
|
||||
while (conn->state == DONE) {
|
||||
/* clean out finished connection */
|
||||
if (conn->conn_close) {
|
||||
LIST_REMOVE(conn, entries);
|
||||
free_connection(conn);
|
||||
free(conn);
|
||||
break;
|
||||
} else {
|
||||
recycle_connection(conn);
|
||||
/* and go right back to recv_request without going through
|
||||
* select() again.
|
||||
* select() again, until state is not DONE
|
||||
*/
|
||||
poll_recv_request(conn);
|
||||
}
|
||||
|
Reference in New Issue
Block a user