]> granicus.if.org Git - apache/commitdiff
* server/connection.c (ap_lingering_close): Fix lingering close to
authorJoe Orton <jorton@apache.org>
Sun, 25 Sep 2005 18:00:43 +0000 (18:00 +0000)
committerJoe Orton <jorton@apache.org>
Sun, 25 Sep 2005 18:00:43 +0000 (18:00 +0000)
really match the 1.3 behaviour: read from the client for up to ~30
seconds in total.  Current behaviour will attempt only 15 read() calls
then give up.

PR: 35292

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@291452 13f79535-47bb-0310-9956-ffa450edef68

server/connection.c

index 9f5949791005dea5a7019e668a641e838fbac3e0..11b499d69ff577c71f1d57ac032dd53e86e7c4a5 100644 (file)
@@ -101,7 +101,7 @@ AP_DECLARE(void) ap_lingering_close(conn_rec *c)
     apr_size_t nbytes = sizeof(dummybuf);
     apr_status_t rc;
     apr_int32_t timeout;
-    apr_int32_t total_linger_time = 0;
+    apr_time_t timeup = 0;
     apr_socket_t *csd = ap_get_module_config(c->conn_config, &core_module);
 
     if (!csd) {
@@ -138,25 +138,31 @@ AP_DECLARE(void) ap_lingering_close(conn_rec *c)
         return;
     }
 
-    /* Read all data from the peer until we reach "end-of-file" (FIN
-     * from peer) or we've exceeded our overall timeout. If the client does
-     * not send us bytes within 2 seconds (a value pulled from Apache 1.3
-     * which seems to work well), close the connection.
+    /* Read available data from the client whilst it continues sending
+     * it, for a maximum time of MAX_SECS_TO_LINGER.  If the client
+     * does not send any data within 2 seconds (a value pulled from
+     * Apache 1.3 which seems to work well), give up.
      */
     timeout = apr_time_from_sec(SECONDS_TO_LINGER);
     apr_socket_timeout_set(csd, timeout);
     apr_socket_opt_set(csd, APR_INCOMPLETE_READ, 1);
-    while (1) {
+
+    /* The common path here is that the initial apr_socket_recv() call
+     * will return 0 bytes read; so that case must avoid the expensive
+     * apr_time_now() call and time arithmetic. */
+
+    do {
         nbytes = sizeof(dummybuf);
         rc = apr_socket_recv(csd, dummybuf, &nbytes);
         if (rc != APR_SUCCESS || nbytes == 0)
             break;
 
-        total_linger_time += SECONDS_TO_LINGER;
-        if (total_linger_time >= MAX_SECS_TO_LINGER) {
-            break;
+        if (timeup == 0) {
+            /* First time through; calculate now + 30 seconds. */
+            timeup = apr_time_now() + apr_time_from_sec(MAX_SECS_TO_LINGER);
+            continue;
         }
-    }
+    } while (apr_time_now() < timeup);
 
     apr_socket_close(csd);
     return;