Lines 184-190
static volatile int dying = 0;
Link Here
|
184 |
static volatile int workers_may_exit = 0; |
184 |
static volatile int workers_may_exit = 0; |
185 |
static volatile int start_thread_may_exit = 0; |
185 |
static volatile int start_thread_may_exit = 0; |
186 |
static volatile int listener_may_exit = 0; |
186 |
static volatile int listener_may_exit = 0; |
187 |
static volatile int listeners_disabled = 0; |
|
|
188 |
static int listener_is_wakeable = 0; /* Pollset supports APR_POLLSET_WAKEABLE */ |
187 |
static int listener_is_wakeable = 0; /* Pollset supports APR_POLLSET_WAKEABLE */ |
189 |
static int num_listensocks = 0; |
188 |
static int num_listensocks = 0; |
190 |
static apr_int32_t conns_this_child; /* MaxConnectionsPerChild, only access |
189 |
static apr_int32_t conns_this_child; /* MaxConnectionsPerChild, only access |
Lines 470-475
static pid_t ap_my_pid; /* Linux getpid()
Link Here
|
470 |
static pid_t parent_pid; |
469 |
static pid_t parent_pid; |
471 |
static apr_os_thread_t *listener_os_thread; |
470 |
static apr_os_thread_t *listener_os_thread; |
472 |
|
471 |
|
|
|
472 |
static int ap_child_slot; /* Current child process slot in scoreboard */ |
473 |
|
473 |
/* The LISTENER_SIGNAL signal will be sent from the main thread to the |
474 |
/* The LISTENER_SIGNAL signal will be sent from the main thread to the |
474 |
* listener thread to wake it up for graceful termination (what a child |
475 |
* listener thread to wake it up for graceful termination (what a child |
475 |
* process from an old generation does when the admin does "apachectl |
476 |
* process from an old generation does when the admin does "apachectl |
Lines 483-505
static apr_os_thread_t *listener_os_thread;
Link Here
|
483 |
*/ |
484 |
*/ |
484 |
static apr_socket_t **worker_sockets; |
485 |
static apr_socket_t **worker_sockets; |
485 |
|
486 |
|
486 |
static void disable_listensocks(int process_slot) |
487 |
static volatile apr_uint32_t listensocks_disabled; |
|
|
488 |
|
489 |
static void disable_listensocks(void) |
487 |
{ |
490 |
{ |
488 |
int i; |
491 |
int i; |
489 |
listeners_disabled = 1; |
492 |
if (apr_atomic_cas32(&listensocks_disabled, 1, 0) != 0) { |
490 |
for (i = 0; i < num_listensocks; i++) { |
493 |
return; |
491 |
apr_pollset_remove(event_pollset, &listener_pollfd[i]); |
|
|
492 |
} |
494 |
} |
493 |
ap_scoreboard_image->parent[process_slot].not_accepting = 1; |
495 |
if (event_pollset) { |
|
|
496 |
for (i = 0; i < num_listensocks; i++) { |
497 |
apr_pollset_remove(event_pollset, &listener_pollfd[i]); |
498 |
} |
499 |
} |
500 |
ap_scoreboard_image->parent[ap_child_slot].not_accepting = 1; |
494 |
} |
501 |
} |
495 |
|
502 |
|
496 |
static void enable_listensocks(int process_slot) |
503 |
static void enable_listensocks(void) |
497 |
{ |
504 |
{ |
498 |
int i; |
505 |
int i; |
499 |
if (listener_may_exit) { |
506 |
if (listener_may_exit |
|
|
507 |
|| apr_atomic_cas32(&listensocks_disabled, 0, 1) != 1) { |
500 |
return; |
508 |
return; |
501 |
} |
509 |
} |
502 |
listeners_disabled = 0; |
|
|
503 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00457) |
510 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00457) |
504 |
"Accepting new connections again: " |
511 |
"Accepting new connections again: " |
505 |
"%u active conns (%u lingering/%u clogged/%u suspended), " |
512 |
"%u active conns (%u lingering/%u clogged/%u suspended), " |
Lines 515-523
static apr_socket_t **worker_sockets;
Link Here
|
515 |
* XXX: This is not yet optimal. If many workers suddenly become available, |
522 |
* XXX: This is not yet optimal. If many workers suddenly become available, |
516 |
* XXX: the parent may kill some processes off too soon. |
523 |
* XXX: the parent may kill some processes off too soon. |
517 |
*/ |
524 |
*/ |
518 |
ap_scoreboard_image->parent[process_slot].not_accepting = 0; |
525 |
ap_scoreboard_image->parent[ap_child_slot].not_accepting = 0; |
519 |
} |
526 |
} |
520 |
|
527 |
|
|
|
528 |
static APR_INLINE apr_uint32_t listeners_disabled(void) |
529 |
{ |
530 |
return apr_atomic_read32(&listensocks_disabled); |
531 |
} |
532 |
|
521 |
static APR_INLINE int connections_above_limit(void) |
533 |
static APR_INLINE int connections_above_limit(void) |
522 |
{ |
534 |
{ |
523 |
apr_uint32_t i_count = ap_queue_info_get_idlers(worker_queue_info); |
535 |
apr_uint32_t i_count = ap_queue_info_get_idlers(worker_queue_info); |
Lines 525-533
static APR_INLINE int connections_above_limit(void
Link Here
|
525 |
apr_uint32_t c_count = apr_atomic_read32(&connection_count); |
537 |
apr_uint32_t c_count = apr_atomic_read32(&connection_count); |
526 |
apr_uint32_t l_count = apr_atomic_read32(&lingering_count); |
538 |
apr_uint32_t l_count = apr_atomic_read32(&lingering_count); |
527 |
if (c_count <= l_count |
539 |
if (c_count <= l_count |
528 |
/* Off by 'listeners_disabled' to avoid flip flop */ |
540 |
/* Off by 'listeners_disabled()' to avoid flip flop */ |
529 |
|| c_count - l_count < (apr_uint32_t)threads_per_child + |
541 |
|| c_count - l_count < (apr_uint32_t)threads_per_child + |
530 |
(i_count - (listeners_disabled != 0)) * |
542 |
(i_count - listeners_disabled()) * |
531 |
(worker_factor / WORKER_FACTOR_SCALE)) { |
543 |
(worker_factor / WORKER_FACTOR_SCALE)) { |
532 |
return 0; |
544 |
return 0; |
533 |
} |
545 |
} |
Lines 590-595
static void close_worker_sockets(void)
Link Here
|
590 |
static void wakeup_listener(void) |
602 |
static void wakeup_listener(void) |
591 |
{ |
603 |
{ |
592 |
listener_may_exit = 1; |
604 |
listener_may_exit = 1; |
|
|
605 |
disable_listensocks(); |
593 |
|
606 |
|
594 |
/* Unblock the listener if it's poll()ing */ |
607 |
/* Unblock the listener if it's poll()ing */ |
595 |
if (event_pollset && listener_is_wakeable) { |
608 |
if (event_pollset && listener_is_wakeable) { |
Lines 793-799
static apr_status_t decrement_connection_count(voi
Link Here
|
793 |
is_last_connection = !apr_atomic_dec32(&connection_count); |
806 |
is_last_connection = !apr_atomic_dec32(&connection_count); |
794 |
if (listener_is_wakeable |
807 |
if (listener_is_wakeable |
795 |
&& ((is_last_connection && listener_may_exit) |
808 |
&& ((is_last_connection && listener_may_exit) |
796 |
|| (listeners_disabled && !connections_above_limit()))) { |
809 |
|| (listeners_disabled() && !connections_above_limit()))) { |
797 |
apr_pollset_wakeup(event_pollset); |
810 |
apr_pollset_wakeup(event_pollset); |
798 |
} |
811 |
} |
799 |
return APR_SUCCESS; |
812 |
return APR_SUCCESS; |
Lines 1270-1286
static void check_infinite_requests(void)
Link Here
|
1270 |
} |
1283 |
} |
1271 |
} |
1284 |
} |
1272 |
|
1285 |
|
1273 |
static void close_listeners(int process_slot, int *closed) |
1286 |
static void close_listeners(int *closed) |
1274 |
{ |
1287 |
{ |
1275 |
if (!*closed) { |
1288 |
if (!*closed) { |
1276 |
int i; |
1289 |
int i; |
1277 |
disable_listensocks(process_slot); |
|
|
1278 |
ap_close_listeners_ex(my_bucket->listeners); |
1290 |
ap_close_listeners_ex(my_bucket->listeners); |
1279 |
*closed = 1; |
1291 |
*closed = 1; |
1280 |
dying = 1; |
1292 |
dying = 1; |
1281 |
ap_scoreboard_image->parent[process_slot].quiescing = 1; |
1293 |
ap_scoreboard_image->parent[ap_child_slot].quiescing = 1; |
1282 |
for (i = 0; i < threads_per_child; ++i) { |
1294 |
for (i = 0; i < threads_per_child; ++i) { |
1283 |
ap_update_child_status_from_indexes(process_slot, i, |
1295 |
ap_update_child_status_from_indexes(ap_child_slot, i, |
1284 |
SERVER_GRACEFUL, NULL); |
1296 |
SERVER_GRACEFUL, NULL); |
1285 |
} |
1297 |
} |
1286 |
/* wake up the main thread */ |
1298 |
/* wake up the main thread */ |
Lines 1794-1801
static void * APR_THREAD_FUNC listener_thread(apr_
Link Here
|
1794 |
ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, |
1806 |
ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, |
1795 |
APLOGNO(03266) |
1807 |
APLOGNO(03266) |
1796 |
"failed to initialize pollset, " |
1808 |
"failed to initialize pollset, " |
1797 |
"attempting to shutdown process gracefully"); |
1809 |
"shutdown process now"); |
1798 |
signal_threads(ST_GRACEFUL); |
1810 |
resource_shortage = 1; |
|
|
1811 |
signal_threads(ST_UNGRACEFUL); |
1799 |
return NULL; |
1812 |
return NULL; |
1800 |
} |
1813 |
} |
1801 |
|
1814 |
|
Lines 1817-1823
static void * APR_THREAD_FUNC listener_thread(apr_
Link Here
|
1817 |
check_infinite_requests(); |
1830 |
check_infinite_requests(); |
1818 |
|
1831 |
|
1819 |
if (listener_may_exit) { |
1832 |
if (listener_may_exit) { |
1820 |
close_listeners(process_slot, &closed); |
1833 |
close_listeners(&closed); |
1821 |
if (terminate_mode == ST_UNGRACEFUL |
1834 |
if (terminate_mode == ST_UNGRACEFUL |
1822 |
|| apr_atomic_read32(&connection_count) == 0) |
1835 |
|| apr_atomic_read32(&connection_count) == 0) |
1823 |
break; |
1836 |
break; |
Lines 1926-1932
static void * APR_THREAD_FUNC listener_thread(apr_
Link Here
|
1926 |
* need to update timeouts (logic is above, so simply restart |
1939 |
* need to update timeouts (logic is above, so simply restart |
1927 |
* the loop). |
1940 |
* the loop). |
1928 |
*/ |
1941 |
*/ |
1929 |
if (!listener_may_exit && !listeners_disabled) { |
1942 |
if (!listener_may_exit && !listeners_disabled()) { |
1930 |
continue; |
1943 |
continue; |
1931 |
} |
1944 |
} |
1932 |
timeout_time = 0; |
1945 |
timeout_time = 0; |
Lines 1942-1954
static void * APR_THREAD_FUNC listener_thread(apr_
Link Here
|
1942 |
} |
1955 |
} |
1943 |
|
1956 |
|
1944 |
if (listener_may_exit) { |
1957 |
if (listener_may_exit) { |
1945 |
close_listeners(process_slot, &closed); |
1958 |
close_listeners(&closed); |
1946 |
if (terminate_mode == ST_UNGRACEFUL |
1959 |
if (terminate_mode == ST_UNGRACEFUL |
1947 |
|| apr_atomic_read32(&connection_count) == 0) |
1960 |
|| apr_atomic_read32(&connection_count) == 0) |
1948 |
break; |
1961 |
break; |
1949 |
} |
1962 |
} |
1950 |
|
1963 |
|
1951 |
while (num) { |
1964 |
for (; num; --num, ++out_pfd) { |
1952 |
listener_poll_type *pt = (listener_poll_type *) out_pfd->client_data; |
1965 |
listener_poll_type *pt = (listener_poll_type *) out_pfd->client_data; |
1953 |
if (pt->type == PT_CSD) { |
1966 |
if (pt->type == PT_CSD) { |
1954 |
/* one of the sockets is readable */ |
1967 |
/* one of the sockets is readable */ |
Lines 2009-2018
static void * APR_THREAD_FUNC listener_thread(apr_
Link Here
|
2009 |
ap_assert(0); |
2022 |
ap_assert(0); |
2010 |
} |
2023 |
} |
2011 |
} |
2024 |
} |
2012 |
else if (pt->type == PT_ACCEPT && !listeners_disabled) { |
2025 |
else if (pt->type == PT_ACCEPT && !listeners_disabled()) { |
2013 |
/* A Listener Socket is ready for an accept() */ |
2026 |
/* A Listener Socket is ready for an accept() */ |
2014 |
if (workers_were_busy) { |
2027 |
if (workers_were_busy) { |
2015 |
disable_listensocks(process_slot); |
2028 |
disable_listensocks(); |
2016 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
2029 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
2017 |
APLOGNO(03268) |
2030 |
APLOGNO(03268) |
2018 |
"All workers busy, not accepting new conns " |
2031 |
"All workers busy, not accepting new conns " |
Lines 2019-2025
static void * APR_THREAD_FUNC listener_thread(apr_
Link Here
|
2019 |
"in this process"); |
2032 |
"in this process"); |
2020 |
} |
2033 |
} |
2021 |
else if (connections_above_limit()) { |
2034 |
else if (connections_above_limit()) { |
2022 |
disable_listensocks(process_slot); |
2035 |
disable_listensocks(); |
2023 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
2036 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
2024 |
APLOGNO(03269) |
2037 |
APLOGNO(03269) |
2025 |
"Too many open connections (%u), " |
2038 |
"Too many open connections (%u), " |
Lines 2048-2055
static void * APR_THREAD_FUNC listener_thread(apr_
Link Here
|
2048 |
ap_server_conf, APLOGNO(03097) |
2061 |
ap_server_conf, APLOGNO(03097) |
2049 |
"Failed to create transaction pool"); |
2062 |
"Failed to create transaction pool"); |
2050 |
apr_allocator_destroy(allocator); |
2063 |
apr_allocator_destroy(allocator); |
|
|
2064 |
resource_shortage = 1; |
2051 |
signal_threads(ST_GRACEFUL); |
2065 |
signal_threads(ST_GRACEFUL); |
2052 |
return NULL; |
2066 |
continue; |
2053 |
} |
2067 |
} |
2054 |
apr_allocator_owner_set(allocator, ptrans); |
2068 |
apr_allocator_owner_set(allocator, ptrans); |
2055 |
} |
2069 |
} |
Lines 2118-2126
static void * APR_THREAD_FUNC listener_thread(apr_
Link Here
|
2118 |
push_timer2worker(te); |
2132 |
push_timer2worker(te); |
2119 |
} |
2133 |
} |
2120 |
} |
2134 |
} |
2121 |
out_pfd++; |
2135 |
} /* for processing poll */ |
2122 |
num--; |
|
|
2123 |
} /* while for processing poll */ |
2124 |
|
2136 |
|
2125 |
/* XXX possible optimization: stash the current time for use as |
2137 |
/* XXX possible optimization: stash the current time for use as |
2126 |
* r->request_time for new requests |
2138 |
* r->request_time for new requests |
Lines 2192-2205
static void * APR_THREAD_FUNC listener_thread(apr_
Link Here
|
2192 |
} |
2204 |
} |
2193 |
} |
2205 |
} |
2194 |
|
2206 |
|
2195 |
if (listeners_disabled |
2207 |
if (listeners_disabled() |
2196 |
&& !workers_were_busy |
2208 |
&& !workers_were_busy |
2197 |
&& !connections_above_limit()) { |
2209 |
&& !connections_above_limit()) { |
2198 |
enable_listensocks(process_slot); |
2210 |
enable_listensocks(); |
2199 |
} |
2211 |
} |
2200 |
} /* listener main loop */ |
2212 |
} /* listener main loop */ |
2201 |
|
2213 |
|
2202 |
close_listeners(process_slot, &closed); |
2214 |
close_listeners(&closed); |
2203 |
ap_queue_term(worker_queue); |
2215 |
ap_queue_term(worker_queue); |
2204 |
|
2216 |
|
2205 |
apr_thread_exit(thd, APR_SUCCESS); |
2217 |
apr_thread_exit(thd, APR_SUCCESS); |
Lines 2649-2654
static void child_main(int child_num_arg, int chil
Link Here
|
2649 |
retained->mpm->mpm_state = AP_MPMQ_STARTING; |
2661 |
retained->mpm->mpm_state = AP_MPMQ_STARTING; |
2650 |
|
2662 |
|
2651 |
ap_my_pid = getpid(); |
2663 |
ap_my_pid = getpid(); |
|
|
2664 |
ap_child_slot = child_num_arg; |
2652 |
ap_fatal_signal_child_setup(ap_server_conf); |
2665 |
ap_fatal_signal_child_setup(ap_server_conf); |
2653 |
apr_pool_create(&pchild, pconf); |
2666 |
apr_pool_create(&pchild, pconf); |
2654 |
|
2667 |
|
Lines 3625-3630
static int event_pre_config(apr_pool_t * pconf, ap
Link Here
|
3625 |
event_pollset = NULL; |
3638 |
event_pollset = NULL; |
3626 |
worker_queue_info = NULL; |
3639 |
worker_queue_info = NULL; |
3627 |
listener_os_thread = NULL; |
3640 |
listener_os_thread = NULL; |
|
|
3641 |
listensocks_disabled = 0; |
3628 |
|
3642 |
|
3629 |
return OK; |
3643 |
return OK; |
3630 |
} |
3644 |
} |