Only in httpd-trunk.new: 1
Only in httpd-trunk.new: httpd-trunk
diff -ru httpd-trunk/server/mpm/event/event.c httpd-trunk.new/server/mpm/event/event.c
--- httpd-trunk/server/mpm/event/event.c	2014-10-05 13:32:37.258992697 -0400
+++ httpd-trunk.new/server/mpm/event/event.c	2014-10-07 04:29:32.249986340 -0400
@@ -358,6 +358,8 @@
 #define MAX_SPAWN_RATE        (32)
 #endif
     int hold_off_on_exponential_spawning;
+    int *bucket;    /* bucket array for the httpd child processes */
+    int previous_daemons_limit;
 } event_retained_data;
 static event_retained_data *retained;
 
@@ -366,8 +368,7 @@
 static ap_pod_t **pod;
 static ap_pod_t *child_pod;
 static ap_listen_rec *child_listen;
-static int *bucket;    /* bucket array for the httpd child processes */
-
+static int *current_bucket;
 /* The event MPM respects a couple of runtime flags that can aid
  * in debugging. Setting the -DNO_DETACH flag will prevent the root process
  * from detaching from its controlling terminal. Additionally, setting
@@ -2430,7 +2431,7 @@
 
     /* close unused listeners and pods */
     for (i = 0; i < num_buckets; i++) {
-        if (i != bucket[child_num_arg]) {
+        if (i != current_bucket[child_num_arg]) {
             lr = mpm_listen[i];
             while(lr) {
                 apr_socket_close(lr->sd);
@@ -2597,8 +2598,8 @@
         retained->max_daemons_limit = slot + 1;
     }
 
-    child_listen = mpm_listen[bucket[slot]];
-    child_pod = pod[bucket[slot]];
+    child_listen = mpm_listen[current_bucket[slot]];
+    child_pod = pod[current_bucket[slot]];
 
     if (one_process) {
         set_signals();
@@ -2667,7 +2668,7 @@
         if (ap_scoreboard_image->parent[i].pid != 0) {
             continue;
         }
-        bucket[i] = i % num_buckets;
+        current_bucket[i] = i % num_buckets;
         if (make_child(ap_server_conf, i) < 0) {
             break;
         }
@@ -2733,7 +2734,7 @@
                                    for loop if no pid?  not much else matters */
                 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
                     && ps->generation == retained->my_generation &&
-                    bucket[i] == child_bucket)
+                    current_bucket[i] == child_bucket)
                 {
                     ++idle_thread_count;
                 }
@@ -2840,7 +2841,7 @@
                              idle_thread_count, total_non_dead);
             }
             for (i = 0; i < free_length; ++i) {
-                bucket[free_slots[i]] = child_bucket;
+                current_bucket[free_slots[i]] = child_bucket;
                 make_child(ap_server_conf, free_slots[i]);
             }
             /* the next time around we want to spawn twice as many if this
@@ -2912,7 +2913,7 @@
                 ap_scoreboard_image->parent[child_slot].quiescing = 0;
                 if (processed_status == APEXIT_CHILDSICK) {
                     /* resource shortage, minimize the fork rate */
-                    retained->idle_spawn_rate[bucket[child_slot]] = 1;
+                    retained->idle_spawn_rate[current_bucket[child_slot]] = 1;
                 }
                 else if (remaining_children_to_start
                          && child_slot < ap_daemons_limit) {
@@ -2977,6 +2978,11 @@
     }
 }
 
+static apr_status_t free_bucket(void *bucket) {
+    free(*(int **)bucket);
+    return APR_SUCCESS;
+}
+
 static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
 {
     int remaining_children_to_start;
@@ -2985,6 +2991,23 @@
 
     ap_log_pid(pconf, ap_pid_fname);
 
+    if (ap_daemons_limit < num_buckets)
+        ap_daemons_limit = num_buckets;
+
+    current_bucket = apr_palloc(_pconf, sizeof(int) *  ap_daemons_limit);
+
+    if (ap_daemons_limit > retained->previous_daemons_limit) {
+        retained->bucket = (int *)realloc(retained->bucket, sizeof(int) * ap_daemons_limit);
+        for (i = 0; i < retained->previous_daemons_limit; i++) {
+            current_bucket[i] = retained->bucket[i];
+        }
+    }
+    else {
+        for (i = 0; i < ap_daemons_limit; i++) {
+            current_bucket[i] = retained->bucket[i];
+        }
+    }
+
     if (!retained->is_graceful) {
         if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
             mpm_state = AP_MPMQ_STOPPING;
@@ -2996,11 +3019,11 @@
         ap_scoreboard_image->global->running_generation = retained->my_generation;
     }
 
-    bucket = apr_palloc(_pconf, sizeof(int) *  ap_daemons_limit);
-
     restart_pending = shutdown_pending = 0;
     set_signals();
     /* Don't thrash... */
+    if (min_spare_threads < num_buckets * threads_per_child)
+        min_spare_threads = num_buckets * threads_per_child;
     if (max_spare_threads < min_spare_threads + threads_per_child * num_buckets)
         max_spare_threads = min_spare_threads + threads_per_child * num_buckets;
 
@@ -3013,6 +3036,9 @@
      * that, so we'll just keep track of how many we're
      * supposed to start up without the 1 second penalty between each fork.
      */
+    if (ap_daemons_to_start < num_buckets) {
+        ap_daemons_to_start = num_buckets;
+    }
     remaining_children_to_start = ap_daemons_to_start;
     if (remaining_children_to_start > ap_daemons_limit) {
         remaining_children_to_start = ap_daemons_limit;
@@ -3136,6 +3162,10 @@
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00493)
                      AP_SIG_GRACEFUL_STRING
                      " received.  Doing graceful restart");
+        for (i = 0; i < ap_daemons_limit; i++) {
+            retained->bucket[i] = current_bucket[i];
+        }
+        retained->previous_daemons_limit = ap_daemons_limit;
         /* wake up the children...time to die.  But we'll have more soon */
         for (i = 0; i < num_buckets; i++) {
             ap_mpm_podx_killpg(pod[i], ap_daemons_limit, AP_MPM_PODX_GRACEFUL);
@@ -3151,6 +3181,10 @@
          * and a SIGHUP, we may as well use the same signal, because some user
          * pthreads are stealing signals from us left and right.
          */
+        for (i = 0; i < ap_daemons_limit; i++) {
+            retained->bucket[i] = -1;
+        }
+        retained->previous_daemons_limit = ap_daemons_limit;
         for (i = 0; i < num_buckets; i++) {
             ap_mpm_podx_killpg(pod[i], ap_daemons_limit, AP_MPM_PODX_RESTART);
         }
@@ -3195,8 +3229,8 @@
 
     enable_default_listener = 1;
     if (have_so_reuseport) {
-#ifdef _SC_NPROCESSORS_ONLN
-        num_of_cores = sysconf(_SC_NPROCESSORS_ONLN);
+#ifdef _SC_NPROCESSORS_CONF
+        num_of_cores = sysconf(_SC_NPROCESSORS_CONF);
 #else
         num_of_cores = 1;
 #endif
@@ -3270,10 +3304,24 @@
                          "atomics not working as expected - add32 of negative number");
             return HTTP_INTERNAL_SERVER_ERROR;
         }
-        retained->idle_spawn_rate = apr_palloc(pconf, sizeof(int) * num_buckets);
+        retained->idle_spawn_rate = apr_palloc(ap_server_conf->process->pool,
+                                               sizeof(int) * num_buckets);
         for (i = 0; i< num_buckets; i++) {
             retained->idle_spawn_rate[i] = 1;
         }
+        if (ap_daemons_limit < num_buckets) {
+            ap_daemons_limit = num_buckets;
+        }
+        retained->bucket = (int*)malloc(sizeof(int) * ap_daemons_limit);
+        if (!retained->bucket) {
+            ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, APLOGNO()
+                         "could not allocate buckets");
+        }
+        for (i = 0; i < ap_daemons_limit; i++) {
+            retained->bucket[i] = -1;
+        }
+        apr_pool_cleanup_register(ap_server_conf->process->pool, &retained->bucket,
+                                  free_bucket, apr_pool_cleanup_null);
         rv = apr_pollset_create(&event_pollset, 1, plog,
                                 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
         if (rv != APR_SUCCESS) {
@@ -3353,6 +3401,9 @@
         }
         server_limit = 1;
     }
+    else if (server_limit < num_buckets) {
+        server_limit = num_buckets;
+    }
 
     /* you cannot change ServerLimit across a restart; ignore
      * any such attempts
diff -ru httpd-trunk/server/mpm/prefork/prefork.c httpd-trunk.new/server/mpm/prefork/prefork.c
--- httpd-trunk/server/mpm/prefork/prefork.c	2014-10-05 17:24:10.695891972 -0400
+++ httpd-trunk.new/server/mpm/prefork/prefork.c	2014-10-07 01:21:27.911054806 -0400
@@ -100,8 +100,7 @@
 static ap_pod_t *child_pod;
 static apr_proc_mutex_t *child_mutex;
 static ap_listen_rec *child_listen;
-static int *bucket;    /* bucket array for the httpd child processes */
-
+static int *current_bucket;
 
 /* data retained by prefork across load/unload of the module
  * allocated on first call to pre-config hook; located on
@@ -130,6 +129,8 @@
 #define MAX_SPAWN_RATE  (32)
 #endif
     int hold_off_on_exponential_spawning;
+    int *bucket;    /* bucket array for the httpd child processes */
+    int previous_daemons_limit;
 } prefork_retained_data;
 static prefork_retained_data *retained;
 
@@ -534,7 +535,7 @@
 
     /* close unused listeners and pods */
     for (i = 0; i < num_buckets; i++) {
-        if (i != bucket[my_child_num]) {
+        if (i != current_bucket[my_child_num]) {
             lr = mpm_listen[i];
             while(lr) {
                 apr_socket_close(lr->sd);
@@ -758,9 +759,9 @@
         retained->max_daemons_limit = slot + 1;
     }
 
-    child_listen = mpm_listen[bucket[slot]];
-    child_mutex = accept_mutex[bucket[slot]];
-    child_pod = pod[bucket[slot]];
+    child_listen = mpm_listen[current_bucket[slot]];
+    child_mutex = accept_mutex[current_bucket[slot]];
+    child_pod = pod[current_bucket[slot]];
 
     if (one_process) {
         apr_signal(SIGHUP, sig_term);
@@ -849,7 +850,7 @@
         if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
             continue;
         }
-        bucket[i] = i % num_buckets;
+        current_bucket[i] = i % num_buckets;
         if (make_child(ap_server_conf, i) < 0) {
             break;
         }
@@ -937,7 +938,7 @@
                     idle_count, total_non_dead);
             }
             for (i = 0; i < free_length; ++i) {
-                bucket[free_slots[i]]= (++bucket_make_child_record) % num_buckets;
+                current_bucket[free_slots[i]]= (++bucket_make_child_record) % num_buckets;
                 make_child(ap_server_conf, free_slots[i]);
             }
             /* the next time around we want to spawn twice as many if this
@@ -956,6 +957,11 @@
     }
 }
 
+static apr_status_t free_bucket(void *bucket) {
+    free(*(int **)bucket);
+    return APR_SUCCESS;
+}
+
 /*****************************************************************
  * Executive routines.
  */
@@ -969,7 +975,22 @@
 
     ap_log_pid(pconf, ap_pid_fname);
 
-    bucket = apr_palloc(_pconf, sizeof(int) *  ap_daemons_limit);
+    if (ap_daemons_limit < num_buckets)
+        ap_daemons_limit = num_buckets;
+
+    current_bucket = apr_palloc(_pconf, sizeof(int) *  ap_daemons_limit);
+    if (ap_daemons_limit > retained->previous_daemons_limit) {
+        retained->bucket = (int *)realloc(retained->bucket, sizeof(int) * ap_daemons_limit);
+        for (i = 0; i < retained->previous_daemons_limit; i++) {
+            current_bucket[i] = retained->bucket[i];
+        }
+    }
+    else {
+        for (i = 0; i < ap_daemons_limit; i++) {
+            current_bucket[i] = retained->bucket[i];
+        }
+    }
+
     /* Initialize cross-process accept lock for each bucket*/
     accept_mutex = apr_palloc(_pconf, sizeof(apr_proc_mutex_t *) * num_buckets);
     for (i = 0; i < num_buckets; i++) {
@@ -997,11 +1018,13 @@
 
     if (one_process) {
         AP_MONCONTROL(1);
-        bucket[0] = 0;
+        current_bucket[0] = 0;
         make_child(ap_server_conf, 0);
         /* NOTREACHED */
     }
     else {
+    if (ap_daemons_min_free < num_buckets)  /* Don't thrash... */
+        ap_daemons_min_free = num_buckets;
     if (ap_daemons_max_free < ap_daemons_min_free + num_buckets)  /* Don't thrash... */
         ap_daemons_max_free = ap_daemons_min_free + num_buckets;
 
@@ -1013,6 +1036,9 @@
      * start more than that, so we'll just keep track of how many we're
      * supposed to start up without the 1 second penalty between each fork.
      */
+    if (ap_daemons_to_start < num_buckets) {
+        ap_daemons_to_start = num_buckets;
+    }
     remaining_children_to_start = ap_daemons_to_start;
     if (remaining_children_to_start > ap_daemons_limit) {
         remaining_children_to_start = ap_daemons_limit;
@@ -1153,7 +1179,6 @@
         ap_remove_pid(pconf, ap_pid_fname);
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00169)
                     "caught SIGTERM, shutting down");
-
         return DONE;
     } else if (shutdown_pending) {
         /* Time to perform a graceful shut down:
@@ -1220,7 +1245,6 @@
          * really dead.
          */
         ap_unixd_killpg(getpgrp(), SIGTERM);
-
         return DONE;
     }
 
@@ -1243,6 +1267,10 @@
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00171)
                     "Graceful restart requested, doing restart");
 
+        for (i = 0; i < ap_daemons_limit; i++) {
+            retained->bucket[i] = current_bucket[i];
+        }
+        retained->previous_daemons_limit = ap_daemons_limit;
         /* kill off the idle ones */
         for (i = 0; i < num_buckets; i++) {
             ap_mpm_pod_killpg(pod[i], retained->max_daemons_limit);
@@ -1272,6 +1300,10 @@
         if (ap_unixd_killpg(getpgrp(), SIGHUP) < 0) {
             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00172) "killpg SIGHUP");
         }
+        for (i = 0; i < ap_daemons_limit; i++) {
+            retained->bucket[i] = -1;
+        }
+        retained->previous_daemons_limit = ap_daemons_limit;
         ap_reclaim_child_processes(0, /* Not when just starting up */
                                    prefork_note_child_killed);
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00173)
@@ -1310,8 +1342,8 @@
 
     enable_default_listener = 1;
     if (have_so_reuseport) {
-#ifdef _SC_NPROCESSORS_ONLN
-        num_of_cores = sysconf(_SC_NPROCESSORS_ONLN);
+#ifdef _SC_NPROCESSORS_CONF
+        num_of_cores = sysconf(_SC_NPROCESSORS_CONF);
 #else
         num_of_cores = 1;
 #endif
@@ -1346,6 +1378,7 @@
     int no_detach, debug, foreground;
     apr_status_t rv;
     const char *userdata_key = "mpm_prefork_module";
+    int i;
 
     mpm_state = AP_MPMQ_STARTING;
 
@@ -1384,6 +1417,19 @@
                 return HTTP_INTERNAL_SERVER_ERROR;
             }
         }
+        if (ap_daemons_limit < num_buckets) {
+            ap_daemons_limit = num_buckets;
+        }
+        retained->bucket = (int*)malloc(sizeof(int) * ap_daemons_limit);
+        if (!retained->bucket) {
+            ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, APLOGNO()
+                         "could not allocate buckets");
+        }
+        for (i = 0; i < ap_daemons_limit; i++) {
+            retained->bucket[i] = -1;
+        }
+        apr_pool_cleanup_register(ap_server_conf->process->pool, &retained->bucket,
+                                  free_bucket, apr_pool_cleanup_null);
     }
 
     parent_pid = ap_my_pid = getpid();
@@ -1437,7 +1483,9 @@
         }
         server_limit = 1;
     }
-
+    else if (server_limit < num_buckets) {
+        server_limit = num_buckets;
+    }
     /* you cannot change ServerLimit across a restart; ignore
      * any such attempts
      */
diff -ru httpd-trunk/server/mpm/worker/worker.c httpd-trunk.new/server/mpm/worker/worker.c
--- httpd-trunk/server/mpm/worker/worker.c	2014-10-05 13:32:37.291992697 -0400
+++ httpd-trunk.new/server/mpm/worker/worker.c	2014-10-07 04:28:31.247987173 -0400
@@ -168,6 +168,8 @@
 #define MAX_SPAWN_RATE        (32)
 #endif
     int hold_off_on_exponential_spawning;
+    int *bucket;    /* bucket array for the httpd child processes */
+    int previous_daemons_limit;
 } worker_retained_data;
 static worker_retained_data *retained;
 
@@ -226,7 +228,7 @@
 static apr_proc_mutex_t **accept_mutex;
 static apr_proc_mutex_t *child_mutex;
 static ap_listen_rec *child_listen;
-static int *bucket;    /* bucket array for the httpd child processes */
+static int *current_bucket;
 
 #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 #define SAFE_ACCEPT(stmt) (child_listen->next ? (stmt) : APR_SUCCESS)
@@ -1237,7 +1239,7 @@
 
     /* close unused listeners and pods */
     for (i = 0; i < num_buckets; i++) {
-        if (i != bucket[child_num_arg]) {
+        if (i != current_bucket[child_num_arg]) {
             lr = mpm_listen[i];
             while(lr) {
                 apr_socket_close(lr->sd);
@@ -1407,9 +1409,9 @@
         retained->max_daemons_limit = slot + 1;
     }
 
-    child_listen = mpm_listen[bucket[slot]];
-    child_mutex = accept_mutex[bucket[slot]];
-    child_pod = pod[bucket[slot]];
+    child_listen = mpm_listen[current_bucket[slot]];
+    child_mutex = accept_mutex[current_bucket[slot]];
+    child_pod = pod[current_bucket[slot]];
 
     if (one_process) {
         set_signals();
@@ -1476,7 +1478,7 @@
         if (ap_scoreboard_image->parent[i].pid != 0) {
             continue;
         }
-        bucket[i] = i % num_buckets;
+        current_bucket[i] = i % num_buckets;
         if (make_child(ap_server_conf, i) < 0) {
             break;
         }
@@ -1542,7 +1544,7 @@
                 if (status <= SERVER_READY &&
                         !ps->quiescing &&
                         ps->generation == retained->my_generation &&
-                        bucket[i] == child_bucket) {
+                        current_bucket[i] == child_bucket) {
                     ++idle_thread_count;
                 }
                 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
@@ -1661,7 +1663,7 @@
                              idle_thread_count, total_non_dead);
             }
             for (i = 0; i < free_length; ++i) {
-                bucket[free_slots[i]] = child_bucket;
+                current_bucket[free_slots[i]] = child_bucket;
                 make_child(ap_server_conf, free_slots[i]);
             }
             /* the next time around we want to spawn twice as many if this
@@ -1732,7 +1734,7 @@
                 ap_scoreboard_image->parent[child_slot].quiescing = 0;
                 if (processed_status == APEXIT_CHILDSICK) {
                     /* resource shortage, minimize the fork rate */
-                    retained->idle_spawn_rate[bucket[child_slot]] = 1;
+                    retained->idle_spawn_rate[current_bucket[child_slot]] = 1;
                 }
                 else if (remaining_children_to_start
                     && child_slot < ap_daemons_limit) {
@@ -1796,6 +1798,11 @@
     }
 }
 
+static apr_status_t free_bucket(void *bucket) {
+    free(*(int **)bucket);
+    return APR_SUCCESS;
+}
+
 static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
 {
     int remaining_children_to_start;
@@ -1804,7 +1811,23 @@
 
     ap_log_pid(pconf, ap_pid_fname);
 
-    bucket = apr_palloc(_pconf, sizeof(int) *  ap_daemons_limit);
+    if (ap_daemons_limit < num_buckets)
+        ap_daemons_limit = num_buckets;
+
+    current_bucket = apr_palloc(_pconf, sizeof(int) *  ap_daemons_limit);
+
+    if (ap_daemons_limit > retained->previous_daemons_limit) {
+        retained->bucket = (int *)realloc(retained->bucket, sizeof(int) * ap_daemons_limit);
+        for (i = 0; i < retained->previous_daemons_limit; i++) {
+            current_bucket[i] = retained->bucket[i];
+        }
+    }
+    else {
+        for (i = 0; i < ap_daemons_limit; i++) {
+            current_bucket[i] = retained->bucket[i];
+        }
+    }
+
     /* Initialize cross-process accept lock */
     accept_mutex = apr_palloc(_pconf, sizeof(apr_proc_mutex_t *) * num_buckets);
     for (i = 0; i < num_buckets; i++) {
@@ -1830,6 +1853,8 @@
     restart_pending = shutdown_pending = 0;
     set_signals();
     /* Don't thrash... */
+    if (min_spare_threads < num_buckets * threads_per_child)
+        min_spare_threads = num_buckets * threads_per_child;
     if (max_spare_threads < min_spare_threads + threads_per_child * num_buckets)
         max_spare_threads = min_spare_threads + threads_per_child * num_buckets;
 
@@ -1842,6 +1867,9 @@
      * that, so we'll just keep track of how many we're
      * supposed to start up without the 1 second penalty between each fork.
      */
+    if (ap_daemons_to_start < num_buckets) {
+        ap_daemons_to_start = num_buckets;
+    }
     remaining_children_to_start = ap_daemons_to_start;
     if (remaining_children_to_start > ap_daemons_limit) {
         remaining_children_to_start = ap_daemons_limit;
@@ -1967,6 +1995,10 @@
     if (retained->is_graceful) {
         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00297)
                      AP_SIG_GRACEFUL_STRING " received.  Doing graceful restart");
+        for (i = 0; i < ap_daemons_limit; i++) {
+            retained->bucket[i] = current_bucket[i];
+        }
+        retained->previous_daemons_limit = ap_daemons_limit;
         /* wake up the children...time to die.  But we'll have more soon */
         for (i = 0; i < num_buckets; i++) {
             ap_mpm_podx_killpg(pod[i], ap_daemons_limit, AP_MPM_PODX_GRACEFUL);
@@ -1982,6 +2014,10 @@
          * and a SIGHUP, we may as well use the same signal, because some user
          * pthreads are stealing signals from us left and right.
          */
+        for (i = 0; i < ap_daemons_limit; i++) {
+            retained->bucket[i] = -1;
+        }
+        retained->previous_daemons_limit = ap_daemons_limit;
         for (i = 0; i < num_buckets; i++) {
             ap_mpm_podx_killpg(pod[i], ap_daemons_limit, AP_MPM_PODX_RESTART);
         }
@@ -2023,8 +2059,8 @@
     }
     enable_default_listener = 1;
     if (have_so_reuseport) {
-#ifdef _SC_NPROCESSORS_ONLN
-        num_of_cores = sysconf(_SC_NPROCESSORS_ONLN);
+#ifdef _SC_NPROCESSORS_CONF
+        num_of_cores = sysconf(_SC_NPROCESSORS_CONF);
 #else
         num_of_cores = 1;
 #endif
@@ -2098,10 +2134,24 @@
                 return HTTP_INTERNAL_SERVER_ERROR;
             }
         }
-        retained->idle_spawn_rate = apr_palloc(pconf, sizeof(int) * num_buckets);
+        retained->idle_spawn_rate = apr_palloc(ap_server_conf->process->pool,
+                                               sizeof(int) * num_buckets);
         for (i = 0; i< num_buckets; i++) {
             retained->idle_spawn_rate[i] = 1;
         }
+        if (ap_daemons_limit < num_buckets) {
+            ap_daemons_limit = num_buckets;
+        }
+        retained->bucket = (int*)malloc(sizeof(int) * ap_daemons_limit);
+        if (!retained->bucket) {
+            ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, APLOGNO()
+                         "could not allocate buckets");
+        }
+        for (i = 0; i < ap_daemons_limit; i++) {
+            retained->bucket[i] = -1;
+        }
+        apr_pool_cleanup_register(ap_server_conf->process->pool, &retained->bucket,
+                                  free_bucket, apr_pool_cleanup_null);
     }
 
     parent_pid = ap_my_pid = getpid();
@@ -2159,6 +2209,9 @@
         }
         server_limit = 1;
     }
+    else if (server_limit < num_buckets) {
+        server_limit = num_buckets;
+    }
 
     /* you cannot change ServerLimit across a restart; ignore
      * any such attempts
@@ -2203,7 +2256,6 @@
         }
         thread_limit = 1;
     }
-
     /* you cannot change ThreadLimit across a restart; ignore
      * any such attempts
      */
