You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by gr...@apache.org on 2004/11/26 22:21:43 UTC

svn commit: r106662 - /httpd/httpd/trunk/modules/http/http_core.c

Author: gregames
Date: Fri Nov 26 13:21:42 2004
New Revision: 106662

URL: http://svn.apache.org/viewcvs?view=rev&rev=106662
Log:
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.

Modified:
   httpd/httpd/trunk/modules/http/http_core.c

Modified: httpd/httpd/trunk/modules/http/http_core.c
Url: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/http/http_core.c?view=diff&rev=106662&p1=httpd/httpd/trunk/modules/http/http_core.c&r1=106661&p2=httpd/httpd/trunk/modules/http/http_core.c&r2=106662
==============================================================================
--- httpd/httpd/trunk/modules/http/http_core.c	(original)
+++ httpd/httpd/trunk/modules/http/http_core.c	Fri Nov 26 13:21:42 2004
@@ -235,44 +235,41 @@
 {
     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);
+            /* else we are pipelining.  Stay in READ_REQUEST_LINE state
+             *  and stay in the loop
+             */
 
-            if (ap_graceful_stop_signalled())
-                break;
-
-            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;