Lines 160-174
Link Here
|
160 |
#endif |
160 |
#endif |
161 |
#define WORKER_FACTOR_SCALE 16 /* scale factor to allow fractional values */ |
161 |
#define WORKER_FACTOR_SCALE 16 /* scale factor to allow fractional values */ |
162 |
static unsigned int worker_factor = DEFAULT_WORKER_FACTOR * WORKER_FACTOR_SCALE; |
162 |
static unsigned int worker_factor = DEFAULT_WORKER_FACTOR * WORKER_FACTOR_SCALE; |
|
|
163 |
/* AsyncRequestWorkerFactor * 16 */ |
163 |
|
164 |
|
164 |
static int threads_per_child = 0; /* Worker threads per child */ |
165 |
static int threads_per_child = 0; /* ThreadsPerChild */ |
165 |
static int ap_daemons_to_start = 0; |
166 |
static int ap_daemons_to_start = 0; /* StartServers */ |
166 |
static int min_spare_threads = 0; |
167 |
static int min_spare_threads = 0; /* MinSpareThreads */ |
167 |
static int max_spare_threads = 0; |
168 |
static int max_spare_threads = 0; /* MaxSpareThreads */ |
168 |
static int ap_daemons_limit = 0; |
169 |
static int ap_daemons_limit = 0; /* MaxRequestWorkers / ThreadsPerChild */ |
169 |
static int max_workers = 0; |
170 |
static int max_workers = 0; /* MaxRequestWorkers */ |
170 |
static int server_limit = 0; |
171 |
static int server_limit = 0; /* ServerLimit */ |
171 |
static int thread_limit = 0; |
172 |
static int thread_limit = 0; /* ThreadLimit */ |
|
|
173 |
static int sb_max_daemon_idx = 0; |
172 |
static int had_healthy_child = 0; |
174 |
static int had_healthy_child = 0; |
173 |
static int dying = 0; |
175 |
static int dying = 0; |
174 |
static int workers_may_exit = 0; |
176 |
static int workers_may_exit = 0; |
Lines 181-186
Link Here
|
181 |
static apr_uint32_t lingering_count = 0; /* Number of connections in lingering close */ |
183 |
static apr_uint32_t lingering_count = 0; /* Number of connections in lingering close */ |
182 |
static apr_uint32_t suspended_count = 0; /* Number of suspended connections */ |
184 |
static apr_uint32_t suspended_count = 0; /* Number of suspended connections */ |
183 |
static apr_uint32_t clogged_count = 0; /* Number of threads processing ssl conns */ |
185 |
static apr_uint32_t clogged_count = 0; /* Number of threads processing ssl conns */ |
|
|
186 |
static apr_uint32_t threads_shutdown = 0; /* Number of threads that have shutdown |
187 |
early during graceful termination */ |
184 |
static int resource_shortage = 0; |
188 |
static int resource_shortage = 0; |
185 |
static fd_queue_t *worker_queue; |
189 |
static fd_queue_t *worker_queue; |
186 |
static fd_queue_info_t *worker_queue_info; |
190 |
static fd_queue_info_t *worker_queue_info; |
Lines 288-296
Link Here
|
288 |
/* The structure used to pass unique initialization info to each thread */ |
292 |
/* The structure used to pass unique initialization info to each thread */ |
289 |
typedef struct |
293 |
typedef struct |
290 |
{ |
294 |
{ |
291 |
int pid; |
295 |
int pslot; /* process slot */ |
292 |
int tid; |
296 |
int tslot; /* worker slot of the thread */ |
293 |
int sd; |
|
|
294 |
} proc_info; |
297 |
} proc_info; |
295 |
|
298 |
|
296 |
/* Structure used to pass information to the thread responsible for |
299 |
/* Structure used to pass information to the thread responsible for |
Lines 911-916
Link Here
|
911 |
|| apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) { |
914 |
|| apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) { |
912 |
apr_socket_close(csd); |
915 |
apr_socket_close(csd); |
913 |
ap_push_pool(worker_queue_info, cs->p); |
916 |
ap_push_pool(worker_queue_info, cs->p); |
|
|
917 |
if (dying) |
918 |
ap_queue_interrupt_one(worker_queue); |
914 |
return 0; |
919 |
return 0; |
915 |
} |
920 |
} |
916 |
return start_lingering_close_common(cs, 0); |
921 |
return start_lingering_close_common(cs, 0); |
Lines 934-939
Link Here
|
934 |
AP_DEBUG_ASSERT(0); |
939 |
AP_DEBUG_ASSERT(0); |
935 |
} |
940 |
} |
936 |
ap_push_pool(worker_queue_info, cs->p); |
941 |
ap_push_pool(worker_queue_info, cs->p); |
|
|
942 |
if (dying) |
943 |
ap_queue_interrupt_one(worker_queue); |
937 |
return 0; |
944 |
return 0; |
938 |
} |
945 |
} |
939 |
|
946 |
|
Lines 1208-1213
Link Here
|
1208 |
{ |
1215 |
{ |
1209 |
if (!*closed) { |
1216 |
if (!*closed) { |
1210 |
int i; |
1217 |
int i; |
|
|
1218 |
worker_score *ws; |
1211 |
disable_listensocks(process_slot); |
1219 |
disable_listensocks(process_slot); |
1212 |
ap_close_listeners_ex(my_bucket->listeners); |
1220 |
ap_close_listeners_ex(my_bucket->listeners); |
1213 |
*closed = 1; |
1221 |
*closed = 1; |
Lines 1214-1224
Link Here
|
1214 |
dying = 1; |
1222 |
dying = 1; |
1215 |
ap_scoreboard_image->parent[process_slot].quiescing = 1; |
1223 |
ap_scoreboard_image->parent[process_slot].quiescing = 1; |
1216 |
for (i = 0; i < threads_per_child; ++i) { |
1224 |
for (i = 0; i < threads_per_child; ++i) { |
|
|
1225 |
ws = ap_get_scoreboard_worker_from_indexes(process_slot, i); |
1226 |
if (ws->pid != ap_my_pid) { |
1227 |
/* scoreboard slot still in use by previous generation */ |
1228 |
continue; |
1229 |
} |
1217 |
ap_update_child_status_from_indexes(process_slot, i, |
1230 |
ap_update_child_status_from_indexes(process_slot, i, |
1218 |
SERVER_GRACEFUL, NULL); |
1231 |
SERVER_GRACEFUL, NULL); |
1219 |
} |
1232 |
} |
1220 |
/* wake up the main thread */ |
1233 |
/* wake up the main thread */ |
1221 |
kill(ap_my_pid, SIGTERM); |
1234 |
kill(ap_my_pid, SIGTERM); |
|
|
1235 |
|
1236 |
ap_free_idle_pools(worker_queue_info); |
1237 |
ap_queue_interrupt_all(worker_queue); |
1222 |
} |
1238 |
} |
1223 |
} |
1239 |
} |
1224 |
|
1240 |
|
Lines 1439-1444
Link Here
|
1439 |
TO_QUEUE_ELEM_INIT(cs); |
1455 |
TO_QUEUE_ELEM_INIT(cs); |
1440 |
|
1456 |
|
1441 |
ap_push_pool(worker_queue_info, cs->p); |
1457 |
ap_push_pool(worker_queue_info, cs->p); |
|
|
1458 |
if (dying) |
1459 |
ap_queue_interrupt_one(worker_queue); |
1442 |
} |
1460 |
} |
1443 |
|
1461 |
|
1444 |
/* call 'func' for all elements of 'q' with timeout less than 'timeout_time'. |
1462 |
/* call 'func' for all elements of 'q' with timeout less than 'timeout_time'. |
Lines 1518-1524
Link Here
|
1518 |
timer_event_t *te; |
1536 |
timer_event_t *te; |
1519 |
apr_status_t rc; |
1537 |
apr_status_t rc; |
1520 |
proc_info *ti = dummy; |
1538 |
proc_info *ti = dummy; |
1521 |
int process_slot = ti->pid; |
1539 |
int process_slot = ti->pslot; |
1522 |
apr_pool_t *tpool = apr_thread_pool_get(thd); |
1540 |
apr_pool_t *tpool = apr_thread_pool_get(thd); |
1523 |
void *csd = NULL; |
1541 |
void *csd = NULL; |
1524 |
apr_pool_t *ptrans; /* Pool for per-transaction stuff */ |
1542 |
apr_pool_t *ptrans; /* Pool for per-transaction stuff */ |
Lines 1584-1589
Link Here
|
1584 |
*keepalive_q->total, |
1602 |
*keepalive_q->total, |
1585 |
apr_atomic_read32(&lingering_count), |
1603 |
apr_atomic_read32(&lingering_count), |
1586 |
apr_atomic_read32(&suspended_count)); |
1604 |
apr_atomic_read32(&suspended_count)); |
|
|
1605 |
if (dying) { |
1606 |
ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf, |
1607 |
"%u/%u workers shutdown", |
1608 |
apr_atomic_read32(&threads_shutdown), |
1609 |
threads_per_child); |
1610 |
} |
1587 |
apr_thread_mutex_unlock(timeout_mutex); |
1611 |
apr_thread_mutex_unlock(timeout_mutex); |
1588 |
} |
1612 |
} |
1589 |
} |
1613 |
} |
Lines 1818-1828
Link Here
|
1818 |
/* If all workers are busy, we kill older keep-alive connections so that they |
1842 |
/* If all workers are busy, we kill older keep-alive connections so that they |
1819 |
* may connect to another process. |
1843 |
* may connect to another process. |
1820 |
*/ |
1844 |
*/ |
1821 |
if (workers_were_busy && *keepalive_q->total) { |
1845 |
if ((workers_were_busy || dying) && *keepalive_q->total) { |
1822 |
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, |
1846 |
if (!dying) |
1823 |
"All workers are busy, will close %d keep-alive " |
1847 |
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, |
1824 |
"connections", |
1848 |
"All workers are busy, will close %d keep-alive " |
1825 |
*keepalive_q->total); |
1849 |
"connections", |
|
|
1850 |
*keepalive_q->total); |
1826 |
process_timeout_queue(keepalive_q, 0, |
1851 |
process_timeout_queue(keepalive_q, 0, |
1827 |
start_lingering_close_nonblocking); |
1852 |
start_lingering_close_nonblocking); |
1828 |
} |
1853 |
} |
Lines 1869-1874
Link Here
|
1869 |
return NULL; |
1894 |
return NULL; |
1870 |
} |
1895 |
} |
1871 |
|
1896 |
|
|
|
1897 |
/* |
1898 |
* During graceful shutdown, if there are more running worker threads than |
1899 |
* open connections, exit one worker thread. |
1900 |
* |
1901 |
* return 1 if thread should exit, 0 if it should continue running. |
1902 |
*/ |
1903 |
static int worker_thread_should_exit_early(void) |
1904 |
{ |
1905 |
for (;;) { |
1906 |
apr_uint32_t conns = apr_atomic_read32(&connection_count); |
1907 |
apr_uint32_t dead = apr_atomic_read32(&threads_shutdown); |
1908 |
apr_uint32_t newdead; |
1909 |
|
1910 |
AP_DEBUG_ASSERT(dead <= threads_per_child); |
1911 |
if (conns >= threads_per_child - dead) |
1912 |
return 0; |
1913 |
|
1914 |
newdead = dead + 1; |
1915 |
if (apr_atomic_cas32(&threads_shutdown, newdead, dead) == dead) { |
1916 |
/* |
1917 |
* No other thread has exited in the mean time, safe to exit |
1918 |
* this one. |
1919 |
*/ |
1920 |
return 1; |
1921 |
} |
1922 |
} |
1923 |
} |
1924 |
|
1872 |
/* XXX For ungraceful termination/restart, we definitely don't want to |
1925 |
/* XXX For ungraceful termination/restart, we definitely don't want to |
1873 |
* wait for active connections to finish but we may want to wait |
1926 |
* wait for active connections to finish but we may want to wait |
1874 |
* for idle workers to get out of the queue code and release mutexes, |
1927 |
* for idle workers to get out of the queue code and release mutexes, |
Lines 1879-1886
Link Here
|
1879 |
static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy) |
1932 |
static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy) |
1880 |
{ |
1933 |
{ |
1881 |
proc_info *ti = dummy; |
1934 |
proc_info *ti = dummy; |
1882 |
int process_slot = ti->pid; |
1935 |
int process_slot = ti->pslot; |
1883 |
int thread_slot = ti->tid; |
1936 |
int thread_slot = ti->tslot; |
1884 |
apr_socket_t *csd = NULL; |
1937 |
apr_socket_t *csd = NULL; |
1885 |
event_conn_state_t *cs; |
1938 |
event_conn_state_t *cs; |
1886 |
apr_pool_t *ptrans; /* Pool for per-transaction stuff */ |
1939 |
apr_pool_t *ptrans; /* Pool for per-transaction stuff */ |
Lines 1915-1920
Link Here
|
1915 |
if (workers_may_exit) { |
1968 |
if (workers_may_exit) { |
1916 |
break; |
1969 |
break; |
1917 |
} |
1970 |
} |
|
|
1971 |
if (dying && worker_thread_should_exit_early()) { |
1972 |
break; |
1973 |
} |
1918 |
|
1974 |
|
1919 |
te = NULL; |
1975 |
te = NULL; |
1920 |
rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te); |
1976 |
rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te); |
Lines 1993-2001
Link Here
|
1993 |
apr_status_t rv; |
2049 |
apr_status_t rv; |
1994 |
|
2050 |
|
1995 |
my_info = (proc_info *) ap_malloc(sizeof(proc_info)); |
2051 |
my_info = (proc_info *) ap_malloc(sizeof(proc_info)); |
1996 |
my_info->pid = my_child_num; |
2052 |
my_info->pslot = my_child_num; |
1997 |
my_info->tid = -1; /* listener thread doesn't have a thread slot */ |
2053 |
my_info->tslot = -1; /* listener thread doesn't have a thread slot */ |
1998 |
my_info->sd = 0; |
|
|
1999 |
rv = apr_thread_create(&ts->listener, thread_attr, listener_thread, |
2054 |
rv = apr_thread_create(&ts->listener, thread_attr, listener_thread, |
2000 |
my_info, pchild); |
2055 |
my_info, pchild); |
2001 |
if (rv != APR_SUCCESS) { |
2056 |
if (rv != APR_SUCCESS) { |
Lines 2104-2117
Link Here
|
2104 |
int status = |
2159 |
int status = |
2105 |
ap_scoreboard_image->servers[child_num_arg][i].status; |
2160 |
ap_scoreboard_image->servers[child_num_arg][i].status; |
2106 |
|
2161 |
|
2107 |
if (status != SERVER_GRACEFUL && status != SERVER_DEAD) { |
2162 |
if (status != SERVER_DEAD) { |
2108 |
continue; |
2163 |
continue; |
2109 |
} |
2164 |
} |
2110 |
|
2165 |
|
2111 |
my_info = (proc_info *) ap_malloc(sizeof(proc_info)); |
2166 |
my_info = (proc_info *) ap_malloc(sizeof(proc_info)); |
2112 |
my_info->pid = my_child_num; |
2167 |
my_info->pslot = my_child_num; |
2113 |
my_info->tid = i; |
2168 |
my_info->tslot = i; |
2114 |
my_info->sd = 0; |
|
|
2115 |
|
2169 |
|
2116 |
/* We are creating threads right now */ |
2170 |
/* We are creating threads right now */ |
2117 |
ap_update_child_status_from_indexes(my_child_num, i, |
2171 |
ap_update_child_status_from_indexes(my_child_num, i, |
Lines 2484-2490
Link Here
|
2484 |
{ |
2538 |
{ |
2485 |
int i; |
2539 |
int i; |
2486 |
|
2540 |
|
2487 |
for (i = 0; number_to_start && i < ap_daemons_limit; ++i) { |
2541 |
for (i = 0; number_to_start && i < sb_max_daemon_idx; ++i) { |
2488 |
if (ap_scoreboard_image->parent[i].pid != 0) { |
2542 |
if (ap_scoreboard_image->parent[i].pid != 0) { |
2489 |
continue; |
2543 |
continue; |
2490 |
} |
2544 |
} |
Lines 2515-2521
Link Here
|
2515 |
last_non_dead = -1; |
2569 |
last_non_dead = -1; |
2516 |
total_non_dead = 0; |
2570 |
total_non_dead = 0; |
2517 |
|
2571 |
|
2518 |
for (i = 0; i < ap_daemons_limit; ++i) { |
2572 |
for (i = 0; i < sb_max_daemon_idx; ++i) { |
2519 |
/* Initialization to satisfy the compiler. It doesn't know |
2573 |
/* Initialization to satisfy the compiler. It doesn't know |
2520 |
* that threads_per_child is always > 0 */ |
2574 |
* that threads_per_child is always > 0 */ |
2521 |
int status = SERVER_DEAD; |
2575 |
int status = SERVER_DEAD; |
Lines 2739-2745
Link Here
|
2739 |
retained->idle_spawn_rate[ps->bucket] = 1; |
2793 |
retained->idle_spawn_rate[ps->bucket] = 1; |
2740 |
} |
2794 |
} |
2741 |
else if (remaining_children_to_start |
2795 |
else if (remaining_children_to_start |
2742 |
&& child_slot < ap_daemons_limit) { |
2796 |
&& child_slot < sb_max_daemon_idx) { |
2743 |
/* we're still doing a 1-for-1 replacement of dead |
2797 |
/* we're still doing a 1-for-1 replacement of dead |
2744 |
* children with new children |
2798 |
* children with new children |
2745 |
*/ |
2799 |
*/ |
Lines 2835-2840
Link Here
|
2835 |
if (max_spare_threads < min_spare_threads + threads_per_child * num_buckets) |
2889 |
if (max_spare_threads < min_spare_threads + threads_per_child * num_buckets) |
2836 |
max_spare_threads = min_spare_threads + threads_per_child * num_buckets; |
2890 |
max_spare_threads = min_spare_threads + threads_per_child * num_buckets; |
2837 |
|
2891 |
|
|
|
2892 |
sb_max_daemon_idx = 10 * ap_daemons_limit; |
2893 |
if (sb_max_daemon_idx > server_limit) { |
2894 |
sb_max_daemon_idx = server_limit; |
2895 |
} |
2838 |
/* If we're doing a graceful_restart then we're going to see a lot |
2896 |
/* If we're doing a graceful_restart then we're going to see a lot |
2839 |
* of children exiting immediately when we get into the main loop |
2897 |
* of children exiting immediately when we get into the main loop |
2840 |
* below (because we just sent them AP_SIG_GRACEFUL). This happens pretty |
2898 |
* below (because we just sent them AP_SIG_GRACEFUL). This happens pretty |
Lines 2876-2882
Link Here
|
2876 |
* Kill child processes, tell them to call child_exit, etc... |
2934 |
* Kill child processes, tell them to call child_exit, etc... |
2877 |
*/ |
2935 |
*/ |
2878 |
for (i = 0; i < num_buckets; i++) { |
2936 |
for (i = 0; i < num_buckets; i++) { |
2879 |
ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit, |
2937 |
ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx, |
2880 |
AP_MPM_PODX_RESTART); |
2938 |
AP_MPM_PODX_RESTART); |
2881 |
} |
2939 |
} |
2882 |
ap_reclaim_child_processes(1, /* Start with SIGTERM */ |
2940 |
ap_reclaim_child_processes(1, /* Start with SIGTERM */ |
Lines 2900-2906
Link Here
|
2900 |
/* Close our listeners, and then ask our children to do same */ |
2958 |
/* Close our listeners, and then ask our children to do same */ |
2901 |
ap_close_listeners(); |
2959 |
ap_close_listeners(); |
2902 |
for (i = 0; i < num_buckets; i++) { |
2960 |
for (i = 0; i < num_buckets; i++) { |
2903 |
ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit, |
2961 |
ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx, |
2904 |
AP_MPM_PODX_GRACEFUL); |
2962 |
AP_MPM_PODX_GRACEFUL); |
2905 |
} |
2963 |
} |
2906 |
ap_relieve_child_processes(event_note_child_killed); |
2964 |
ap_relieve_child_processes(event_note_child_killed); |
Lines 2928-2934
Link Here
|
2928 |
ap_relieve_child_processes(event_note_child_killed); |
2986 |
ap_relieve_child_processes(event_note_child_killed); |
2929 |
|
2987 |
|
2930 |
active_children = 0; |
2988 |
active_children = 0; |
2931 |
for (index = 0; index < ap_daemons_limit; ++index) { |
2989 |
for (index = 0; index < sb_max_daemon_idx; ++index) { |
2932 |
if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) { |
2990 |
if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) { |
2933 |
active_children = 1; |
2991 |
active_children = 1; |
2934 |
/* Having just one child is enough to stay around */ |
2992 |
/* Having just one child is enough to stay around */ |
Lines 2943-2949
Link Here
|
2943 |
* really dead. |
3001 |
* really dead. |
2944 |
*/ |
3002 |
*/ |
2945 |
for (i = 0; i < num_buckets; i++) { |
3003 |
for (i = 0; i < num_buckets; i++) { |
2946 |
ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit, |
3004 |
ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx, |
2947 |
AP_MPM_PODX_RESTART); |
3005 |
AP_MPM_PODX_RESTART); |
2948 |
} |
3006 |
} |
2949 |
ap_reclaim_child_processes(1, event_note_child_killed); |
3007 |
ap_reclaim_child_processes(1, event_note_child_killed); |
Lines 2972-2978
Link Here
|
2972 |
" received. Doing graceful restart"); |
3030 |
" received. Doing graceful restart"); |
2973 |
/* wake up the children...time to die. But we'll have more soon */ |
3031 |
/* wake up the children...time to die. But we'll have more soon */ |
2974 |
for (i = 0; i < num_buckets; i++) { |
3032 |
for (i = 0; i < num_buckets; i++) { |
2975 |
ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit, |
3033 |
ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx, |
2976 |
AP_MPM_PODX_GRACEFUL); |
3034 |
AP_MPM_PODX_GRACEFUL); |
2977 |
} |
3035 |
} |
2978 |
|
3036 |
|
Lines 2987-2993
Link Here
|
2987 |
* pthreads are stealing signals from us left and right. |
3045 |
* pthreads are stealing signals from us left and right. |
2988 |
*/ |
3046 |
*/ |
2989 |
for (i = 0; i < num_buckets; i++) { |
3047 |
for (i = 0; i < num_buckets; i++) { |
2990 |
ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit, |
3048 |
ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx, |
2991 |
AP_MPM_PODX_RESTART); |
3049 |
AP_MPM_PODX_RESTART); |
2992 |
} |
3050 |
} |
2993 |
|
3051 |
|
Lines 3211-3216
Link Here
|
3211 |
server_limit = DEFAULT_SERVER_LIMIT; |
3269 |
server_limit = DEFAULT_SERVER_LIMIT; |
3212 |
thread_limit = DEFAULT_THREAD_LIMIT; |
3270 |
thread_limit = DEFAULT_THREAD_LIMIT; |
3213 |
ap_daemons_limit = server_limit; |
3271 |
ap_daemons_limit = server_limit; |
|
|
3272 |
sb_max_daemon_idx = server_limit; |
3214 |
threads_per_child = DEFAULT_THREADS_PER_CHILD; |
3273 |
threads_per_child = DEFAULT_THREADS_PER_CHILD; |
3215 |
max_workers = ap_daemons_limit * threads_per_child; |
3274 |
max_workers = ap_daemons_limit * threads_per_child; |
3216 |
had_healthy_child = 0; |
3275 |
had_healthy_child = 0; |