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:
Tom Dryer
2021-06-13 13:33:42 -07:00
parent 35c488b95f
commit 6f049638b6

View File

@ -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);
}