From b5e94158692ef51e87d3c7ea4273c26410f16797 Mon Sep 17 00:00:00 2001 From: Greg Ames Date: Fri, 26 Nov 2004 21:21:42 +0000 Subject: [PATCH] ap_process_http_async_connection (used by the Event MPM): fix CLOSE_WAITs/leaked connections. The logic to deal with ap_read_request failures got lost when merging in the HTTP pipelining fix. If ap_read_request fails, the connection state should get set to CONN_STATE_LINGER so the MPM will invoke lingering close. Test case: client sends a Connection: keepalive header then closes the connection before the keepalive timeout pops. Also add a comment to make the pipelining flow more obvious. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@106662 13f79535-47bb-0310-9956-ffa450edef68 --- modules/http/http_core.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/modules/http/http_core.c b/modules/http/http_core.c index 3f10a3db64..89a7c92ad7 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -235,44 +235,41 @@ static int ap_process_http_async_connection(conn_rec *c) { request_rec *r; conn_state_t *cs = c->cs; - - switch (cs->state) { - case CONN_STATE_READ_REQUEST_LINE: + + AP_DEBUG_ASSERT(cs->state == CONN_STATE_READ_REQUEST_LINE); + + while (cs->state == CONN_STATE_READ_REQUEST_LINE) { ap_update_child_status(c->sbh, SERVER_BUSY_READ, NULL); - while ((r = ap_read_request(c)) != NULL) { - c->keepalive = AP_CONN_UNKNOWN; + + if ((r = ap_read_request(c))) { + c->keepalive = AP_CONN_UNKNOWN; /* process the request if it was read without error */ + ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, r); - if (r->status == HTTP_OK) ap_process_request(r); if (ap_extended_status) ap_increment_counts(c->sbh, r); - if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted) { + if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted + || ap_graceful_stop_signalled()) { cs->state = CONN_STATE_LINGER; - break; } - else { + else if (!c->data_in_input_filters) { cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE; } - apr_pool_destroy(r->pool); - - if (ap_graceful_stop_signalled()) - break; + /* else we are pipelining. Stay in READ_REQUEST_LINE state + * and stay in the loop + */ - if (c->data_in_input_filters) { - continue; - } - break; + apr_pool_destroy(r->pool); + } + else { /* ap_read_request failed - client may have closed */ + cs->state = CONN_STATE_LINGER; } - break; - default: - AP_DEBUG_ASSERT(0); - cs->state = CONN_STATE_LINGER; } return OK; -- 2.50.1