]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mpm_event: Follow up to r1918482: CONN_STATE_LINGER* are not the last anymore.
authorYann Ylavic <ylavic@apache.org>
Fri, 21 Jun 2024 15:38:47 +0000 (15:38 +0000)
committerYann Ylavic <ylavic@apache.org>
Fri, 21 Jun 2024 15:38:47 +0000 (15:38 +0000)
Since CONN_STATE_ASYNC_WAITIO, we cannot check for < or >= CONN_STATE_LINGER
anymore to determine if in an lingering close state, so let's add a new
CONN_STATE_IS_LINGERING_CLOSE() macro for this and use it in mpm_event.

The test for state == CONN_STATE_LINGER in process_lingering_close() is a
bit weak too in order to call ap_start_lingering_close() the first time only,
so have a conn_state->linger_started flag instead.

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

server/mpm/event/event.c

index 0e6ce8a2ee87df69d0b657657b1240f6c866e1ef..403f9a3c9399d0d0be069fd18ff4c7193e0931fc 100644 (file)
 #define apr_time_from_msec(x) (x * 1000)
 #endif
 
+#define CONN_STATE_IS_LINGERING_CLOSE(s) ((s) >= CONN_STATE_LINGER && \
+                                          (s) <= CONN_STATE_LINGER_SHORT)
 #ifndef MAX_SECS_TO_LINGER
 #define MAX_SECS_TO_LINGER 30
 #endif
@@ -252,8 +254,11 @@ struct event_conn_state_t {
     conn_state_t pub;
     /** chaining in defer_linger_chain */
     struct event_conn_state_t *chain;
-    /** Is lingering close from defer_lingering_close()? */
-    int deferred_linger;
+    unsigned int 
+        /** Is lingering close from defer_lingering_close()? */
+        deferred_linger :1,
+        /** Has ap_start_lingering_close() been called? */
+        linger_started  :1;
 };
 
 APR_RING_HEAD(timeout_head_t, event_conn_state_t);
@@ -933,7 +938,7 @@ static void close_connection(event_conn_state_t *cs)
  */
 static int shutdown_connection(event_conn_state_t *cs)
 {
-    if (cs->pub.state < CONN_STATE_LINGER) {
+    if (!CONN_STATE_IS_LINGERING_CLOSE(cs->pub.state)) {
         apr_table_setn(cs->c->notes, "short-lingering-close", "1");
         defer_lingering_close(cs);
     }
@@ -1114,7 +1119,7 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
         c->id = conn_id;
     }
 
-    if (cs->pub.state >= CONN_STATE_LINGER) {
+    if (CONN_STATE_IS_LINGERING_CLOSE(cs->pub.state)) {
         goto lingering_close;
     }
 
@@ -1349,7 +1354,7 @@ static apr_status_t event_resume_suspended (conn_rec *c)
     apr_atomic_dec32(&suspended_count);
     c->suspended_baton = NULL;
 
-    if (cs->pub.state < CONN_STATE_LINGER) {
+    if (!CONN_STATE_IS_LINGERING_CLOSE(cs->pub.state)) {
         cs->queue_timestamp = apr_time_now();
         notify_suspend(cs);
 
@@ -1362,7 +1367,6 @@ static apr_status_t event_resume_suspended (conn_rec *c)
         apr_thread_mutex_unlock(timeout_mutex);
     }
     else {
-        cs->pub.state = CONN_STATE_LINGER;
         process_lingering_close(cs);
     }
 
@@ -1769,9 +1773,12 @@ static void process_lingering_close(event_conn_state_t *cs)
 
     ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, cs->c,
                   "lingering close from state %i", (int)cs->pub.state);
-    AP_DEBUG_ASSERT(cs->pub.state >= CONN_STATE_LINGER);
+    AP_DEBUG_ASSERT(CONN_STATE_IS_LINGERING_CLOSE(cs->pub.state));
+
+    if (!cs->linger_started) {
+        cs->pub.state = CONN_STATE_LINGER;
+        cs->linger_started = 1;
 
-    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);