Commit 9bd8d857 authored by Greg Ames's avatar Greg Ames
Browse files

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
parent 42f20757
Loading
Loading
Loading
Loading
+18 −21
Original line number Diff line number Diff line
@@ -236,44 +236,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);
                                                       
            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);
        }
	break;
    default:
        AP_DEBUG_ASSERT(0);
        else {   /* ap_read_request failed - client may have closed */
            cs->state = CONN_STATE_LINGER;
        }
    }

    return OK;
}