]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge r1855306 from trunk:
authorYann Ylavic <ylavic@apache.org>
Wed, 13 Mar 2019 08:59:54 +0000 (08:59 +0000)
committerYann Ylavic <ylavic@apache.org>
Wed, 13 Mar 2019 08:59:54 +0000 (08:59 +0000)
MPMs unix: bind the bucket number of each child to its slot number

We need not remember each child's bucket number in SHM for restarts, for the
lifetime of the httpd main process the bucket number can be bound to the slot
number such that: bucket = slot % num_buckets.

This both simplifies the logic and helps children maintenance per bucket in
threaded MPMs, where previously perform_idle_server_maintenance() could create
or kill children processes for the buckets it was not in charge of.

Submitted by: ylavic
Reviewed by: ylavic, rpluem, jorton

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855378 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/scoreboard.h
server/mpm/event/event.c
server/mpm/prefork/prefork.c
server/mpm/worker/worker.c

diff --git a/CHANGES b/CHANGES
index e79251389d5e549900926b98cff90ce28c66f3e8..6b5608021199e7f987e311694a94f2b207255a5d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.4.39
 
+  *) MPMs unix: bind the bucket number of each child to its slot number, for a
+     more efficient per bucket maintenance. [Yann Ylavic]
+
   *) mod_auth_digest: Fix a race condition. Authentication with valid
      credentials could be refused in case of concurrent accesses from
      different users.  PR 63124.  [Simon Kappel <simon.kappel axis.com>]
index 9376da246b0761b9d9fb2c8d534d7f541db34519..92d198d6de1ff8b06b5518a98e4fabc0f1f61fc2 100644 (file)
@@ -148,7 +148,9 @@ struct process_score {
     apr_uint32_t lingering_close;   /* async connections in lingering close */
     apr_uint32_t keep_alive;        /* async connections in keep alive */
     apr_uint32_t suspended;         /* connections suspended by some module */
-    int bucket;             /* Listener bucket used by this child */
+    int bucket;  /* Listener bucket used by this child; this field is DEPRECATED
+                  * and no longer updated by the MPMs (i.e. always zero).
+                  */
 };
 
 /* Scoreboard is now in 'local' memory, since it isn't updated once created,
index 4cfb09c5b28520c32139b7e7b24fefda398a181e..5e5af339adc84179da3f4dd106680ef26822d06c 100644 (file)
@@ -2696,7 +2696,6 @@ static int make_child(server_rec * s, int slot, int bucket)
 
     ap_scoreboard_image->parent[slot].quiescing = 0;
     ap_scoreboard_image->parent[slot].not_accepting = 0;
-    ap_scoreboard_image->parent[slot].bucket = bucket;
     event_note_child_started(slot, pid);
     active_daemons++;
     retained->total_daemons++;
@@ -2735,6 +2734,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
          * that threads_per_child is always > 0 */
         int status = SERVER_DEAD;
         int child_threads_active = 0;
+        int bucket = i % num_buckets;
 
         if (i >= retained->max_daemons_limit &&
             free_length == retained->idle_spawn_rate[child_bucket]) {
@@ -2758,7 +2758,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
                  */
                 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
                     && ps->generation == retained->mpm->my_generation
-                    && ps->bucket == child_bucket)
+                    && bucket == child_bucket)
                 {
                     ++idle_thread_count;
                 }
@@ -2769,7 +2769,9 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
             last_non_dead = i;
         }
         active_thread_count += child_threads_active;
-        if (!ps->pid && free_length < retained->idle_spawn_rate[child_bucket])
+        if (!ps->pid
+                && bucket == child_bucket
+                && free_length < retained->idle_spawn_rate[child_bucket])
             free_slots[free_length++] = i;
         else if (child_threads_active == threads_per_child)
             had_healthy_child = 1;
@@ -2962,13 +2964,14 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
                 retained->total_daemons--;
                 if (processed_status == APEXIT_CHILDSICK) {
                     /* resource shortage, minimize the fork rate */
-                    retained->idle_spawn_rate[ps->bucket] = 1;
+                    retained->idle_spawn_rate[child_slot % num_buckets] = 1;
                 }
                 else if (remaining_children_to_start) {
                     /* we're still doing a 1-for-1 replacement of dead
                      * children with new children
                      */
-                    make_child(ap_server_conf, child_slot, ps->bucket);
+                    make_child(ap_server_conf, child_slot,
+                               child_slot % num_buckets);
                     --remaining_children_to_start;
                 }
             }
index 8efda72ee18c08dd4fb692c6f21b7f4489c87683..7c0062573012b4754ad0e076a07d27a491e7a409 100644 (file)
@@ -637,8 +637,9 @@ static void child_main(int child_num_arg, int child_bucket)
 }
 
 
-static int make_child(server_rec *s, int slot, int bucket)
+static int make_child(server_rec *s, int slot)
 {
+    int bucket = slot % retained->mpm->num_buckets;
     int pid;
 
     if (slot + 1 > retained->max_daemons_limit) {
@@ -716,7 +717,6 @@ static int make_child(server_rec *s, int slot, int bucket)
         child_main(slot, bucket);
     }
 
-    ap_scoreboard_image->parent[slot].bucket = bucket;
     prefork_note_child_started(slot, pid);
 
     return 0;
@@ -732,7 +732,7 @@ static void startup_children(int number_to_start)
         if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
             continue;
         }
-        if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
+        if (make_child(ap_server_conf, i) < 0) {
             break;
         }
         --number_to_start;
@@ -741,8 +741,6 @@ static void startup_children(int number_to_start)
 
 static void perform_idle_server_maintenance(apr_pool_t *p)
 {
-    static int bucket_make_child_record = -1;
-    static int bucket_kill_child_record = -1;
     int i;
     int idle_count;
     worker_score *ws;
@@ -789,6 +787,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
     }
     retained->max_daemons_limit = last_non_dead + 1;
     if (idle_count > ap_daemons_max_free) {
+        static int bucket_kill_child_record = -1;
         /* kill off one child... we use the pod because that'll cause it to
          * shut down gracefully, in case it happened to pick up a request
          * while we were counting
@@ -819,10 +818,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
                     idle_count, total_non_dead);
             }
             for (i = 0; i < free_length; ++i) {
-                bucket_make_child_record++;
-                bucket_make_child_record %= retained->mpm->num_buckets;
-                make_child(ap_server_conf, free_slots[i],
-                           bucket_make_child_record);
+                make_child(ap_server_conf, free_slots[i]);
             }
             /* the next time around we want to spawn twice as many if this
              * wasn't good enough, but not if we've just done a graceful
@@ -867,7 +863,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
 
     if (one_process) {
         AP_MONCONTROL(1);
-        make_child(ap_server_conf, 0, 0);
+        make_child(ap_server_conf, 0);
         /* NOTREACHED */
         ap_assert(0);
         return !OK;
@@ -976,8 +972,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
                     /* we're still doing a 1-for-1 replacement of dead
                      * children with new children
                      */
-                    make_child(ap_server_conf, child_slot,
-                               ap_get_scoreboard_process(child_slot)->bucket);
+                    make_child(ap_server_conf, child_slot);
                     --remaining_children_to_start;
                 }
 #if APR_HAS_OTHER_CHILD
index 8012fe29d8d1c9f6b29a61e87905a18eeb6fb4d5..a92794245c5aa44af0d3598f05bdbeeb1495cb0e 100644 (file)
@@ -1339,7 +1339,6 @@ static int make_child(server_rec *s, int slot, int bucket)
         worker_note_child_lost_slot(slot, pid);
     }
     ap_scoreboard_image->parent[slot].quiescing = 0;
-    ap_scoreboard_image->parent[slot].bucket = bucket;
     worker_note_child_started(slot, pid);
     return 0;
 }
@@ -1388,6 +1387,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
         int any_dead_threads = 0;
         int all_dead_threads = 1;
         int child_threads_active = 0;
+        int bucket = i % num_buckets;
 
         if (i >= retained->max_daemons_limit &&
             totally_free_length == retained->idle_spawn_rate[child_bucket]) {
@@ -1420,7 +1420,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
                 if (status <= SERVER_READY &&
                         !ps->quiescing &&
                         ps->generation == retained->mpm->my_generation &&
-                        ps->bucket == child_bucket) {
+                        bucket == child_bucket) {
                     ++idle_thread_count;
                 }
                 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
@@ -1430,6 +1430,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
         }
         active_thread_count += child_threads_active;
         if (any_dead_threads
+                && bucket == child_bucket
                 && totally_free_length < retained->idle_spawn_rate[child_bucket]
                 && free_length < MAX_SPAWN_RATE / num_buckets
                 && (!ps->pid               /* no process in the slot */
@@ -1615,14 +1616,15 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
                 ps->quiescing = 0;
                 if (processed_status == APEXIT_CHILDSICK) {
                     /* resource shortage, minimize the fork rate */
-                    retained->idle_spawn_rate[ps->bucket] = 1;
+                    retained->idle_spawn_rate[child_slot % num_buckets] = 1;
                 }
                 else if (remaining_children_to_start
                     && child_slot < ap_daemons_limit) {
                     /* we're still doing a 1-for-1 replacement of dead
                      * children with new children
                      */
-                    make_child(ap_server_conf, child_slot, ps->bucket);
+                    make_child(ap_server_conf, child_slot,
+                               child_slot % num_buckets);
                     --remaining_children_to_start;
                 }
             }