You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by yl...@apache.org on 2021/07/22 14:59:58 UTC

svn commit: r1891717 - /httpd/httpd/trunk/server/mpm/event/event.c

Author: ylavic
Date: Thu Jul 22 14:59:57 2021
New Revision: 1891717

URL: http://svn.apache.org/viewvc?rev=1891717&view=rev
Log:
mpm_event: handle lingering close fully in process_lingering_close().

* server/mpm/event/event.c (start_lingering_close_blocking): Axe the function
  and put the code directly in process_lingering_close() on the first call when
  cs->pub.state == CONN_STATE_LINGER, this simplifies lingering close handling
  from process_socket() and event_resume_suspended().

No functional changes.

Follow up to r1891716.
Github: #208

Modified:
    httpd/httpd/trunk/server/mpm/event/event.c

Modified: httpd/httpd/trunk/server/mpm/event/event.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/mpm/event/event.c?rev=1891717&r1=1891716&r2=1891717&view=diff
==============================================================================
--- httpd/httpd/trunk/server/mpm/event/event.c (original)
+++ httpd/httpd/trunk/server/mpm/event/event.c Thu Jul 22 14:59:57 2021
@@ -829,48 +829,6 @@ static void notify_resume(event_conn_sta
     ap_run_resume_connection(cs->c, cs->r);
 }
 
-static void close_connection(event_conn_state_t *cs);
-
-/*
- * Close our side of the connection, flushing data to the client first.
- * Pre-condition: cs is not in any timeout queue and not in the pollset,
- *                timeout_mutex is not locked
- * return: 0 if connection is fully closed,
- *         1 if connection is lingering
- * May only be called by worker thread.
- */
-static int start_lingering_close_blocking(event_conn_state_t *cs)
-{
-    apr_socket_t *csd = cs->pfd.desc.s;
-
-    /* defer_lingering_close() may have bumped lingering_count already */
-    if (!cs->deferred_linger) {
-        apr_atomic_inc32(&lingering_count);
-    }
-
-    apr_socket_timeout_set(csd, apr_time_from_sec(SECONDS_TO_LINGER));
-    if (ap_start_lingering_close(cs->c)) {
-        notify_suspend(cs);
-        close_connection(cs);
-        return DONE;
-    }
-
-    cs->queue_timestamp = apr_time_now();
-    /*
-     * If some module requested a shortened waiting period, only wait for
-     * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
-     * DoS attacks.
-     */
-    if (apr_table_get(cs->c->notes, "short-lingering-close")) {
-        cs->pub.state = CONN_STATE_LINGER_SHORT;
-    }
-    else {
-        cs->pub.state = CONN_STATE_LINGER_NORMAL;
-    }
-    notify_suspend(cs);
-    return OK;
-}
-
 /*
  * Defer flush and close of the connection by adding it to defer_linger_chain,
  * for a worker to grab it and do the job (should that be blocking).
@@ -1279,12 +1237,10 @@ read_request:
         return;
     }
 
-    if (cs->pub.state == CONN_STATE_LINGER) {
-        rc = start_lingering_close_blocking(cs);
-    }
-    if (rc == OK && (cs->pub.state == CONN_STATE_LINGER_NORMAL ||
-                     cs->pub.state == CONN_STATE_LINGER_SHORT)) {
+    /* CONN_STATE_LINGER[_*] fall through process_lingering_close() */
+    if (cs->pub.state >= CONN_STATE_LINGER) {
         process_lingering_close(cs);
+        return;
     }
 }
 
@@ -1304,14 +1260,7 @@ static apr_status_t event_resume_suspend
     apr_atomic_dec32(&suspended_count);
     c->suspended_baton = NULL;
 
-    if (cs->pub.state == CONN_STATE_LINGER) {
-        int rc = start_lingering_close_blocking(cs);
-        if (rc == OK && (cs->pub.state == CONN_STATE_LINGER_NORMAL ||
-                         cs->pub.state == CONN_STATE_LINGER_SHORT)) {
-            process_lingering_close(cs);
-        }
-    }
-    else {
+    if (cs->pub.state < CONN_STATE_LINGER) {
         cs->queue_timestamp = apr_time_now();
         cs->pub.state = CONN_STATE_WRITE_COMPLETION;
         notify_suspend(cs);
@@ -1322,6 +1271,10 @@ static apr_status_t event_resume_suspend
         apr_pollset_add(event_pollset, &cs->pfd);
         apr_thread_mutex_unlock(timeout_mutex);
     }
+    else {
+        cs->pub.state = CONN_STATE_LINGER;
+        process_lingering_close(cs);
+    }
 
     return OK;
 }
@@ -1723,6 +1676,34 @@ static void process_lingering_close(even
                   "lingering close from state %i", (int)cs->pub.state);
     AP_DEBUG_ASSERT(cs->pub.state >= CONN_STATE_LINGER);
 
+    if (cs->pub.state == CONN_STATE_LINGER) {
+        /* defer_lingering_close() may have bumped lingering_count already */
+        if (!cs->deferred_linger) {
+            apr_atomic_inc32(&lingering_count);
+        }
+
+        apr_socket_timeout_set(csd, apr_time_from_sec(SECONDS_TO_LINGER));
+        if (ap_start_lingering_close(cs->c)) {
+            notify_suspend(cs);
+            close_connection(cs);
+            return;
+        }
+
+        cs->queue_timestamp = apr_time_now();
+        /*
+         * If some module requested a shortened waiting period, only wait for
+         * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
+         * DoS attacks.
+         */
+        if (apr_table_get(cs->c->notes, "short-lingering-close")) {
+            cs->pub.state = CONN_STATE_LINGER_SHORT;
+        }
+        else {
+            cs->pub.state = CONN_STATE_LINGER_NORMAL;
+        }
+        notify_suspend(cs);
+    }
+
     apr_socket_timeout_set(csd, 0);
     do {
         nbytes = sizeof(dummybuf);