]> granicus.if.org Git - apache/commitdiff
ap_process_http_async_connection (used by the Event MPM):
authorGreg Ames <gregames@apache.org>
Fri, 26 Nov 2004 21:21:42 +0000 (21:21 +0000)
committerGreg Ames <gregames@apache.org>
Fri, 26 Nov 2004 21:21:42 +0000 (21:21 +0000)
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

index 3f10a3db64cf8a493dccbf2d892ac6101e2db7fa..89a7c92ad78e9ace7c64871dde282fc932fff041 100644 (file)
@@ -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;