00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "apr.h"
00018 #include "apr_portable.h"
00019 #include "apr_strings.h"
00020 #include "apr_file_io.h"
00021 #include "apr_thread_proc.h"
00022 #include "apr_signal.h"
00023 #include "apr_thread_cond.h"
00024 #include "apr_thread_mutex.h"
00025 #include "apr_proc_mutex.h"
00026 #define APR_WANT_STRFUNC
00027 #include "apr_want.h"
00028
00029 #if APR_HAVE_UNISTD_H
00030 #include <unistd.h>
00031 #endif
00032 #if APR_HAVE_SYS_SOCKET_H
00033 #include <sys/socket.h>
00034 #endif
00035 #if APR_HAVE_SYS_WAIT_H
00036 #include <sys/wait.h>
00037 #endif
00038 #ifdef HAVE_SYS_PROCESSOR_H
00039 #include <sys/processor.h>
00040 #endif
00041
00042 #if !APR_HAS_THREADS
00043 #error The Leader/Follower MPM requires APR threads, but they are unavailable.
00044 #endif
00045
00046 #define CORE_PRIVATE
00047
00048 #include "ap_config.h"
00049 #include "httpd.h"
00050 #include "http_main.h"
00051 #include "http_log.h"
00052 #include "http_config.h"
00053 #include "http_core.h"
00054 #include "http_connection.h"
00055 #include "ap_mpm.h"
00056 #include "mpm_common.h"
00057 #include "ap_listen.h"
00058 #include "scoreboard.h"
00059 #include "mpm_default.h"
00060 #include "apr_poll.h"
00061
00062 #include <signal.h>
00063 #include <limits.h>
00064
00065 #include "apr_atomic.h"
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 #ifndef DEFAULT_SERVER_LIMIT
00079 #define DEFAULT_SERVER_LIMIT 16
00080 #endif
00081
00082
00083
00084
00085 #ifndef MAX_SERVER_LIMIT
00086 #define MAX_SERVER_LIMIT 20000
00087 #endif
00088
00089
00090
00091
00092
00093
00094
00095
00096 #ifndef DEFAULT_THREAD_LIMIT
00097 #define DEFAULT_THREAD_LIMIT 64
00098 #endif
00099
00100
00101
00102
00103 #ifndef MAX_THREAD_LIMIT
00104 #define MAX_THREAD_LIMIT 20000
00105 #endif
00106
00107
00108
00109
00110
00111 int ap_threads_per_child = 0;
00112 static int ap_daemons_to_start = 0;
00113 static int min_spare_threads = 0;
00114 static int max_spare_threads = 0;
00115 static int ap_daemons_limit = 0;
00116 static int server_limit = DEFAULT_SERVER_LIMIT;
00117 static int first_server_limit;
00118 static int thread_limit = DEFAULT_THREAD_LIMIT;
00119 static int first_thread_limit;
00120 static int changed_limit_at_restart;
00121 static int dying = 0;
00122 static int workers_may_exit = 0;
00123 static int start_thread_may_exit = 0;
00124 static int requests_this_child;
00125 static int num_listensocks = 0;
00126 static int resource_shortage = 0;
00127 static int mpm_state = AP_MPMQ_STARTING;
00128
00129 typedef struct worker_wakeup_info worker_wakeup_info;
00130
00131
00132 typedef struct {
00133 int pid;
00134 int tid;
00135 int sd;
00136 } proc_info;
00137
00138
00139
00140
00141
00142 typedef struct {
00143 apr_thread_t **threads;
00144 int child_num_arg;
00145 apr_threadattr_t *threadattr;
00146 } thread_starter;
00147
00148 #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
00149
00150
00151
00152
00153
00154
00155
00156 int ap_max_daemons_limit = -1;
00157
00158 static ap_pod_t *pod;
00159
00160
00161
00162 server_rec *ap_server_conf;
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 static int one_process = 0;
00178
00179 #ifdef DEBUG_SIGSTOP
00180 int raise_sigstop_flags;
00181 #endif
00182
00183 static apr_pool_t *pconf;
00184 static apr_pool_t *pchild;
00185
00186 static pid_t ap_my_pid;
00187
00188 static pid_t parent_pid;
00189
00190
00191 static apr_proc_mutex_t *accept_mutex;
00192
00193 #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
00194 #define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
00195 #else
00196 #define SAFE_ACCEPT(stmt) (stmt)
00197 #endif
00198
00199
00200
00201
00202 struct worker_wakeup_info {
00203 apr_uint32_t next;
00204
00205
00206 apr_thread_cond_t *cond;
00207 apr_thread_mutex_t *mutex;
00208 };
00209
00210 static worker_wakeup_info *worker_wakeup_create(apr_pool_t *pool)
00211 {
00212 apr_status_t rv;
00213 worker_wakeup_info *wakeup;
00214
00215 wakeup = (worker_wakeup_info *)apr_palloc(pool, sizeof(*wakeup));
00216 if ((rv = apr_thread_cond_create(&wakeup->cond, pool)) != APR_SUCCESS) {
00217 return NULL;
00218 }
00219 if ((rv = apr_thread_mutex_create(&wakeup->mutex, APR_THREAD_MUTEX_DEFAULT,
00220 pool)) != APR_SUCCESS) {
00221 return NULL;
00222 }
00223
00224
00225
00226 apr_thread_mutex_lock(wakeup->mutex);
00227 return wakeup;
00228 }
00229
00230
00231
00232
00233 typedef struct {
00234
00235
00236
00237
00238
00239
00240
00241
00242 apr_uint32_t state;
00243 } worker_stack;
00244
00245 #define STACK_FIRST 0xffff
00246 #define STACK_LIST_END 0xffff
00247 #define STACK_TERMINATED 0x10000
00248 #define STACK_NO_LISTENER 0x20000
00249
00250 static worker_wakeup_info **worker_wakeups = NULL;
00251
00252 static worker_stack* worker_stack_create(apr_pool_t *pool, apr_size_t max)
00253 {
00254 worker_stack *stack = (worker_stack *)apr_palloc(pool, sizeof(*stack));
00255 stack->state = STACK_NO_LISTENER | STACK_LIST_END;
00256 return stack;
00257 }
00258
00259 static apr_status_t worker_stack_wait(worker_stack *stack,
00260 apr_uint32_t worker_id)
00261 {
00262 worker_wakeup_info *wakeup = worker_wakeups[worker_id];
00263
00264 while (1) {
00265 apr_uint32_t state = stack->state;
00266 if (state & (STACK_TERMINATED | STACK_NO_LISTENER)) {
00267 if (state & STACK_TERMINATED) {
00268 return APR_EINVAL;
00269 }
00270 if (apr_atomic_cas(&(stack->state), STACK_LIST_END, state) !=
00271 state) {
00272 continue;
00273 }
00274 else {
00275 return APR_SUCCESS;
00276 }
00277 }
00278 wakeup->next = state;
00279 if (apr_atomic_cas(&(stack->state), worker_id, state) != state) {
00280 continue;
00281 }
00282 else {
00283 return apr_thread_cond_wait(wakeup->cond, wakeup->mutex);
00284 }
00285 }
00286 }
00287
00288 static apr_status_t worker_stack_awaken_next(worker_stack *stack)
00289 {
00290
00291 while (1) {
00292 apr_uint32_t state = stack->state;
00293 apr_uint32_t first = state & STACK_FIRST;
00294 if (first == STACK_LIST_END) {
00295 if (apr_atomic_cas(&(stack->state), state | STACK_NO_LISTENER,
00296 state) != state) {
00297 continue;
00298 }
00299 else {
00300 return APR_SUCCESS;
00301 }
00302 }
00303 else {
00304 worker_wakeup_info *wakeup = worker_wakeups[first];
00305 if (apr_atomic_cas(&(stack->state), (state ^ first) | wakeup->next,
00306 state) != state) {
00307 continue;
00308 }
00309 else {
00310
00311
00312
00313 apr_status_t rv;
00314 if ((rv = apr_thread_mutex_lock(wakeup->mutex)) !=
00315 APR_SUCCESS) {
00316 return rv;
00317 }
00318 if ((rv = apr_thread_mutex_unlock(wakeup->mutex)) !=
00319 APR_SUCCESS) {
00320 return rv;
00321 }
00322 return apr_thread_cond_signal(wakeup->cond);
00323 }
00324 }
00325 }
00326 }
00327
00328 static apr_status_t worker_stack_term(worker_stack *stack)
00329 {
00330 int i;
00331 apr_status_t rv;
00332
00333 while (1) {
00334 apr_uint32_t state = stack->state;
00335 if (apr_atomic_cas(&(stack->state), state | STACK_TERMINATED,
00336 state) == state) {
00337 break;
00338 }
00339 }
00340 for (i = 0; i < ap_threads_per_child; i++) {
00341 if ((rv = worker_stack_awaken_next(stack)) != APR_SUCCESS) {
00342 return rv;
00343 }
00344 }
00345 return APR_SUCCESS;
00346 }
00347
00348 static worker_stack *idle_worker_stack;
00349
00350 #define ST_INIT 0
00351 #define ST_GRACEFUL 1
00352 #define ST_UNGRACEFUL 2
00353
00354 static int terminate_mode = ST_INIT;
00355
00356 static void signal_threads(int mode)
00357 {
00358 if (terminate_mode == mode) {
00359 return;
00360 }
00361 terminate_mode = mode;
00362 mpm_state = AP_MPMQ_STOPPING;
00363 workers_may_exit = 1;
00364
00365 worker_stack_term(idle_worker_stack);
00366 }
00367
00368 AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
00369 {
00370 switch(query_code){
00371 case AP_MPMQ_MAX_DAEMON_USED:
00372 *result = ap_max_daemons_limit;
00373 return APR_SUCCESS;
00374 case AP_MPMQ_IS_THREADED:
00375 *result = AP_MPMQ_STATIC;
00376 return APR_SUCCESS;
00377 case AP_MPMQ_IS_FORKED:
00378 *result = AP_MPMQ_DYNAMIC;
00379 return APR_SUCCESS;
00380 case AP_MPMQ_HARD_LIMIT_DAEMONS:
00381 *result = server_limit;
00382 return APR_SUCCESS;
00383 case AP_MPMQ_HARD_LIMIT_THREADS:
00384 *result = thread_limit;
00385 return APR_SUCCESS;
00386 case AP_MPMQ_MAX_THREADS:
00387 *result = ap_threads_per_child;
00388 return APR_SUCCESS;
00389 case AP_MPMQ_MIN_SPARE_DAEMONS:
00390 *result = 0;
00391 return APR_SUCCESS;
00392 case AP_MPMQ_MIN_SPARE_THREADS:
00393 *result = min_spare_threads;
00394 return APR_SUCCESS;
00395 case AP_MPMQ_MAX_SPARE_DAEMONS:
00396 *result = 0;
00397 return APR_SUCCESS;
00398 case AP_MPMQ_MAX_SPARE_THREADS:
00399 *result = max_spare_threads;
00400 return APR_SUCCESS;
00401 case AP_MPMQ_MAX_REQUESTS_DAEMON:
00402 *result = ap_max_requests_per_child;
00403 return APR_SUCCESS;
00404 case AP_MPMQ_MAX_DAEMONS:
00405 *result = ap_daemons_limit;
00406 return APR_SUCCESS;
00407 case AP_MPMQ_MPM_STATE:
00408 *result = mpm_state;
00409 return APR_SUCCESS;
00410 }
00411 return APR_ENOTIMPL;
00412 }
00413
00414
00415 static void clean_child_exit(int code) __attribute__ ((noreturn));
00416 static void clean_child_exit(int code)
00417 {
00418 mpm_state = AP_MPMQ_STOPPING;
00419 if (pchild) {
00420 apr_pool_destroy(pchild);
00421 }
00422 ap_mpm_pod_close(pod);
00423 exit(code);
00424 }
00425
00426 static void just_die(int sig)
00427 {
00428 clean_child_exit(0);
00429 }
00430
00431
00432
00433
00434
00435
00436 static int volatile shutdown_pending;
00437 static int volatile restart_pending;
00438 static int volatile is_graceful;
00439 static volatile int child_fatal;
00440 ap_generation_t volatile ap_my_generation;
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 static void ap_start_shutdown(void)
00462 {
00463 mpm_state = AP_MPMQ_STOPPING;
00464 if (shutdown_pending == 1) {
00465
00466
00467
00468
00469 return;
00470 }
00471 shutdown_pending = 1;
00472 }
00473
00474
00475 static void ap_start_restart(int graceful)
00476 {
00477 mpm_state = AP_MPMQ_STOPPING;
00478 if (restart_pending == 1) {
00479
00480 return;
00481 }
00482 restart_pending = 1;
00483 is_graceful = graceful;
00484 }
00485
00486 static void sig_term(int sig)
00487 {
00488 if (ap_my_pid == parent_pid) {
00489 ap_start_shutdown();
00490 }
00491 else {
00492 signal_threads(ST_GRACEFUL);
00493 }
00494 }
00495
00496 static void restart(int sig)
00497 {
00498 ap_start_restart(sig == AP_SIG_GRACEFUL);
00499 }
00500
00501 static void set_signals(void)
00502 {
00503 #ifndef NO_USE_SIGACTION
00504 struct sigaction sa;
00505 #endif
00506
00507 if (!one_process) {
00508 ap_fatal_signal_setup(ap_server_conf, pconf);
00509 }
00510
00511 #ifndef NO_USE_SIGACTION
00512 sigemptyset(&sa.sa_mask);
00513 sa.sa_flags = 0;
00514
00515 sa.sa_handler = sig_term;
00516 if (sigaction(SIGTERM, &sa, NULL) < 0)
00517 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
00518 "sigaction(SIGTERM)");
00519 #ifdef SIGINT
00520 if (sigaction(SIGINT, &sa, NULL) < 0)
00521 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
00522 "sigaction(SIGINT)");
00523 #endif
00524 #ifdef SIGXCPU
00525 sa.sa_handler = SIG_DFL;
00526 if (sigaction(SIGXCPU, &sa, NULL) < 0)
00527 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
00528 "sigaction(SIGXCPU)");
00529 #endif
00530 #ifdef SIGXFSZ
00531 sa.sa_handler = SIG_DFL;
00532 if (sigaction(SIGXFSZ, &sa, NULL) < 0)
00533 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
00534 "sigaction(SIGXFSZ)");
00535 #endif
00536 #ifdef SIGPIPE
00537 sa.sa_handler = SIG_IGN;
00538 if (sigaction(SIGPIPE, &sa, NULL) < 0)
00539 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
00540 "sigaction(SIGPIPE)");
00541 #endif
00542
00543
00544
00545 sigaddset(&sa.sa_mask, SIGHUP);
00546 sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
00547 sa.sa_handler = restart;
00548 if (sigaction(SIGHUP, &sa, NULL) < 0)
00549 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
00550 "sigaction(SIGHUP)");
00551 if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
00552 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
00553 "sigaction(" AP_SIG_GRACEFUL_STRING ")");
00554 #else
00555 if (!one_process) {
00556 #ifdef SIGXCPU
00557 apr_signal(SIGXCPU, SIG_DFL);
00558 #endif
00559 #ifdef SIGXFSZ
00560 apr_signal(SIGXFSZ, SIG_DFL);
00561 #endif
00562 }
00563
00564 apr_signal(SIGTERM, sig_term);
00565 #ifdef SIGHUP
00566 apr_signal(SIGHUP, restart);
00567 #endif
00568 #ifdef AP_SIG_GRACEFUL
00569 apr_signal(AP_SIG_GRACEFUL, restart);
00570 #endif
00571 #ifdef SIGPIPE
00572 apr_signal(SIGPIPE, SIG_IGN);
00573 #endif
00574
00575 #endif
00576 }
00577
00578
00579
00580
00581
00582 int ap_graceful_stop_signalled(void)
00583
00584
00585
00586 {
00587 return workers_may_exit;
00588 }
00589
00590
00591
00592
00593
00594 static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num,
00595 int my_thread_num, apr_bucket_alloc_t *bucket_alloc)
00596 {
00597 conn_rec *current_conn;
00598 long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
00599 int csd;
00600 ap_sb_handle_t *sbh;
00601
00602 ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
00603 apr_os_sock_get(&csd, sock);
00604
00605 current_conn = ap_run_create_connection(p, ap_server_conf, sock,
00606 conn_id, sbh, bucket_alloc);
00607 if (current_conn) {
00608 ap_process_connection(current_conn, sock);
00609 ap_lingering_close(current_conn);
00610 }
00611 }
00612
00613
00614
00615
00616 static void check_infinite_requests(void)
00617 {
00618 if (ap_max_requests_per_child) {
00619 signal_threads(ST_GRACEFUL);
00620 }
00621 else {
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 requests_this_child = INT_MAX;
00634 }
00635 }
00636
00637 static void unblock_signal(int sig)
00638 {
00639 sigset_t sig_mask;
00640
00641 sigemptyset(&sig_mask);
00642 sigaddset(&sig_mask, sig);
00643 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
00644 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
00645 #else
00646 pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
00647 #endif
00648 }
00649
00650 static void *worker_thread(apr_thread_t *thd, void * dummy)
00651 {
00652 proc_info * ti = dummy;
00653 int process_slot = ti->pid;
00654 int thread_slot = ti->tid;
00655 apr_uint32_t my_worker_num = (apr_uint32_t)(ti->tid);
00656 apr_pool_t *tpool = apr_thread_pool_get(thd);
00657 void *csd = NULL;
00658 apr_allocator_t *allocator;
00659 apr_pool_t *ptrans;
00660 apr_bucket_alloc_t *bucket_alloc;
00661 int n;
00662 apr_pollfd_t *pollset;
00663 apr_status_t rv;
00664 ap_listen_rec *lr, *last_lr = ap_listeners;
00665 int is_listener;
00666
00667 ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_STARTING, NULL);
00668
00669 free(ti);
00670
00671 apr_allocator_create(&allocator);
00672 apr_allocator_max_free_set(allocator, ap_max_mem_free);
00673
00674 apr_pool_create_ex(&ptrans, NULL, NULL, allocator);
00675 apr_allocator_owner_set(allocator, ptrans);
00676 bucket_alloc = apr_bucket_alloc_create_ex(allocator);
00677
00678 apr_poll_setup(&pollset, num_listensocks, tpool);
00679 for(lr = ap_listeners ; lr != NULL ; lr = lr->next)
00680 apr_poll_socket_add(pollset, lr->sd, APR_POLLIN);
00681
00682
00683
00684 is_listener = 0;
00685 while (!workers_may_exit) {
00686
00687 ap_update_child_status_from_indexes(process_slot, thread_slot,
00688 SERVER_READY, NULL);
00689 if (!is_listener) {
00690
00691 if ((rv = worker_stack_wait(idle_worker_stack, my_worker_num)) !=
00692 APR_SUCCESS) {
00693 if (rv != APR_EINVAL) {
00694 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
00695 "worker_stack_wait failed. Shutting down");
00696 }
00697 break;
00698 }
00699 if (workers_may_exit) {
00700 break;
00701 }
00702 is_listener = 1;
00703 }
00704
00705
00706 if (requests_this_child <= 0) {
00707 check_infinite_requests();
00708 }
00709 if (workers_may_exit) break;
00710
00711 if ((rv = SAFE_ACCEPT(apr_proc_mutex_lock(accept_mutex)))
00712 != APR_SUCCESS) {
00713 int level = APLOG_EMERG;
00714
00715 if (workers_may_exit) {
00716 break;
00717 }
00718 if (ap_scoreboard_image->parent[process_slot].generation !=
00719 ap_scoreboard_image->global->running_generation) {
00720 level = APLOG_DEBUG;
00721 }
00722 ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
00723 "apr_proc_mutex_lock failed. Attempting to shutdown "
00724 "process gracefully.");
00725 signal_threads(ST_GRACEFUL);
00726 break;
00727 }
00728
00729 if (!ap_listeners->next) {
00730
00731 lr = ap_listeners;
00732 }
00733 else {
00734 while (!workers_may_exit) {
00735 apr_status_t ret;
00736 apr_int16_t event;
00737
00738 ret = apr_poll(pollset, num_listensocks, &n, -1);
00739 if (ret != APR_SUCCESS) {
00740 if (APR_STATUS_IS_EINTR(ret)) {
00741 continue;
00742 }
00743
00744
00745
00746 ap_log_error(APLOG_MARK, APLOG_ERR, ret, (const server_rec *)
00747 ap_server_conf, "apr_poll: (listen)");
00748 signal_threads(ST_GRACEFUL);
00749 }
00750
00751 if (workers_may_exit) break;
00752
00753
00754 lr = last_lr;
00755 do {
00756 lr = lr->next;
00757 if (lr == NULL) {
00758 lr = ap_listeners;
00759 }
00760
00761 apr_poll_revents_get(&event, lr->sd, pollset);
00762 if (event & APR_POLLIN) {
00763 last_lr = lr;
00764 goto got_fd;
00765 }
00766 } while (lr != last_lr);
00767 }
00768 }
00769 got_fd:
00770 if (!workers_may_exit) {
00771 rv = lr->accept_func(&csd, lr, ptrans);
00772
00773 AP_DEBUG_ASSERT(rv == APR_SUCCESS || !csd);
00774
00775 if (rv == APR_EGENERAL) {
00776
00777 resource_shortage = 1;
00778 signal_threads(ST_GRACEFUL);
00779 }
00780 if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
00781 != APR_SUCCESS) {
00782 int level = APLOG_EMERG;
00783
00784 if (workers_may_exit) {
00785 break;
00786 }
00787 if (ap_scoreboard_image->parent[process_slot].generation !=
00788 ap_scoreboard_image->global->running_generation) {
00789 level = APLOG_DEBUG;
00790 }
00791 ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
00792 "apr_proc_mutex_unlock failed. Attempting to "
00793 "shutdown process gracefully.");
00794 signal_threads(ST_GRACEFUL);
00795 }
00796 if (csd != NULL) {
00797 is_listener = 0;
00798 worker_stack_awaken_next(idle_worker_stack);
00799 process_socket(ptrans, csd, process_slot,
00800 thread_slot, bucket_alloc);
00801 apr_pool_clear(ptrans);
00802 requests_this_child--;
00803 }
00804 if ((ap_mpm_pod_check(pod) == APR_SUCCESS) ||
00805 (ap_my_generation !=
00806 ap_scoreboard_image->global->running_generation)) {
00807 signal_threads(ST_GRACEFUL);
00808 break;
00809 }
00810 }
00811 else {
00812 if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
00813 != APR_SUCCESS) {
00814 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
00815 "apr_proc_mutex_unlock failed. Attempting to "
00816 "shutdown process gracefully.");
00817 signal_threads(ST_GRACEFUL);
00818 }
00819 break;
00820 }
00821 }
00822
00823 dying = 1;
00824 ap_scoreboard_image->parent[process_slot].quiescing = 1;
00825
00826 worker_stack_term(idle_worker_stack);
00827
00828 ap_update_child_status_from_indexes(process_slot, thread_slot,
00829 (dying) ? SERVER_DEAD : SERVER_GRACEFUL, (request_rec *) NULL);
00830
00831 apr_bucket_alloc_destroy(bucket_alloc);
00832
00833 apr_thread_exit(thd, APR_SUCCESS);
00834 return NULL;
00835 }
00836
00837 static int check_signal(int signum)
00838 {
00839 switch (signum) {
00840 case SIGTERM:
00841 case SIGINT:
00842 return 1;
00843 }
00844 return 0;
00845 }
00846
00847
00848
00849
00850
00851
00852 static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
00853 {
00854 thread_starter *ts = dummy;
00855 apr_thread_t **threads = ts->threads;
00856 apr_threadattr_t *thread_attr = ts->threadattr;
00857 int child_num_arg = ts->child_num_arg;
00858 int my_child_num = child_num_arg;
00859 proc_info *my_info;
00860 apr_status_t rv;
00861 int i;
00862 int threads_created = 0;
00863 int loops;
00864 int prev_threads_created;
00865
00866 idle_worker_stack = worker_stack_create(pchild, ap_threads_per_child);
00867 if (idle_worker_stack == NULL) {
00868 ap_log_error(APLOG_MARK, APLOG_ALERT, 0, ap_server_conf,
00869 "worker_stack_create() failed");
00870 clean_child_exit(APEXIT_CHILDFATAL);
00871 }
00872
00873 worker_wakeups = (worker_wakeup_info **)
00874 apr_palloc(pchild, sizeof(worker_wakeup_info *) *
00875 ap_threads_per_child);
00876
00877 loops = prev_threads_created = 0;
00878 while (1) {
00879 for (i = 0; i < ap_threads_per_child; i++) {
00880 int status = ap_scoreboard_image->servers[child_num_arg][i].status;
00881 worker_wakeup_info *wakeup;
00882
00883 if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
00884 continue;
00885 }
00886
00887 wakeup = worker_wakeup_create(pchild);
00888 if (wakeup == NULL) {
00889 ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0,
00890 ap_server_conf, "worker_wakeup_create failed");
00891 clean_child_exit(APEXIT_CHILDFATAL);
00892 }
00893 worker_wakeups[threads_created] = wakeup;
00894 my_info = (proc_info *)malloc(sizeof(proc_info));
00895 if (my_info == NULL) {
00896 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
00897 "malloc: out of memory");
00898 clean_child_exit(APEXIT_CHILDFATAL);
00899 }
00900 my_info->pid = my_child_num;
00901 my_info->tid = i;
00902 my_info->sd = 0;
00903
00904
00905 ap_update_child_status_from_indexes(my_child_num, i,
00906 SERVER_STARTING, NULL);
00907
00908
00909
00910 rv = apr_thread_create(&threads[i], thread_attr,
00911 worker_thread, my_info, pchild);
00912 if (rv != APR_SUCCESS) {
00913 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
00914 "apr_thread_create: unable to create worker thread");
00915
00916
00917
00918 apr_sleep(10 * APR_USEC_PER_SEC);
00919 clean_child_exit(APEXIT_CHILDFATAL);
00920 }
00921 threads_created++;
00922 }
00923 if (start_thread_may_exit || threads_created == ap_threads_per_child) {
00924 break;
00925 }
00926
00927 apr_sleep(1 * APR_USEC_PER_SEC);
00928 ++loops;
00929 if (loops % 120 == 0) {
00930 if (prev_threads_created == threads_created) {
00931 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
00932 "child %" APR_PID_T_FMT " isn't taking over "
00933 "slots very quickly (%d of %d)",
00934 ap_my_pid, threads_created, ap_threads_per_child);
00935 }
00936 prev_threads_created = threads_created;
00937 }
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 apr_thread_exit(thd, APR_SUCCESS);
00951 return NULL;
00952 }
00953
00954 static void join_workers(apr_thread_t **threads)
00955 {
00956 int i;
00957 apr_status_t rv, thread_rv;
00958
00959 for (i = 0; i < ap_threads_per_child; i++) {
00960 if (threads[i]) {
00961 rv = apr_thread_join(&thread_rv, threads[i]);
00962 if (rv != APR_SUCCESS) {
00963 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
00964 "apr_thread_join: unable to join worker "
00965 "thread %d",
00966 i);
00967 }
00968 }
00969 }
00970 }
00971
00972 static void join_start_thread(apr_thread_t *start_thread_id)
00973 {
00974 apr_status_t rv, thread_rv;
00975
00976 start_thread_may_exit = 1;
00977
00978
00979
00980 rv = apr_thread_join(&thread_rv, start_thread_id);
00981 if (rv != APR_SUCCESS) {
00982 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
00983 "apr_thread_join: unable to join the start "
00984 "thread");
00985 }
00986 }
00987
00988 static void child_main(int child_num_arg)
00989 {
00990 apr_thread_t **threads;
00991 apr_status_t rv;
00992 thread_starter *ts;
00993 apr_threadattr_t *thread_attr;
00994 apr_thread_t *start_thread_id;
00995
00996 mpm_state = AP_MPMQ_STARTING;
00997
00998
00999
01000 ap_my_pid = getpid();
01001 ap_fatal_signal_child_setup(ap_server_conf);
01002 apr_pool_create(&pchild, pconf);
01003
01004
01005 ap_reopen_scoreboard(pchild, NULL, 0);
01006
01007 rv = SAFE_ACCEPT(apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname,
01008 pchild));
01009 if (rv != APR_SUCCESS) {
01010 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
01011 "Couldn't initialize cross-process lock in child");
01012 clean_child_exit(APEXIT_CHILDFATAL);
01013 }
01014
01015 if (unixd_setup_child()) {
01016 clean_child_exit(APEXIT_CHILDFATAL);
01017 }
01018
01019 ap_run_child_init(pchild, ap_server_conf);
01020
01021
01022
01023
01024
01025
01026
01027 rv = apr_setup_signal_thread();
01028 if (rv != APR_SUCCESS) {
01029 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
01030 "Couldn't initialize signal thread");
01031 clean_child_exit(APEXIT_CHILDFATAL);
01032 }
01033
01034 if (ap_max_requests_per_child) {
01035 requests_this_child = ap_max_requests_per_child;
01036 }
01037 else {
01038
01039 requests_this_child = INT_MAX;
01040 }
01041
01042
01043
01044
01045
01046
01047 threads = (apr_thread_t **)calloc(1,
01048 sizeof(apr_thread_t *) * ap_threads_per_child);
01049 if (threads == NULL) {
01050 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
01051 "malloc: out of memory");
01052 clean_child_exit(APEXIT_CHILDFATAL);
01053 }
01054
01055 ts = (thread_starter *)apr_palloc(pchild, sizeof(*ts));
01056
01057 apr_threadattr_create(&thread_attr, pchild);
01058
01059 apr_threadattr_detach_set(thread_attr, 0);
01060
01061 ts->threads = threads;
01062 ts->child_num_arg = child_num_arg;
01063 ts->threadattr = thread_attr;
01064
01065 rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
01066 ts, pchild);
01067 if (rv != APR_SUCCESS) {
01068 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
01069 "apr_thread_create: unable to create worker thread");
01070
01071
01072
01073 apr_sleep(10 * APR_USEC_PER_SEC);
01074 clean_child_exit(APEXIT_CHILDFATAL);
01075 }
01076
01077 mpm_state = AP_MPMQ_RUNNING;
01078
01079
01080
01081 if (one_process) {
01082
01083 apr_signal_thread(check_signal);
01084
01085
01086
01087
01088
01089
01090
01091 join_start_thread(start_thread_id);
01092 signal_threads(ST_UNGRACEFUL);
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 join_workers(threads);
01104 }
01105 else {
01106
01107
01108
01109
01110 unblock_signal(SIGTERM);
01111 join_start_thread(start_thread_id);
01112 join_workers(threads);
01113 }
01114
01115 free(threads);
01116
01117 clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
01118 }
01119
01120 static int make_child(server_rec *s, int slot)
01121 {
01122 int pid;
01123
01124 if (slot + 1 > ap_max_daemons_limit) {
01125 ap_max_daemons_limit = slot + 1;
01126 }
01127
01128 if (one_process) {
01129 set_signals();
01130 ap_scoreboard_image->parent[slot].pid = getpid();
01131 child_main(slot);
01132 }
01133
01134 if ((pid = fork()) == -1) {
01135 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
01136 "fork: Unable to fork new process");
01137
01138
01139
01140
01141 ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD, NULL);
01142
01143
01144
01145
01146 apr_sleep(10 * APR_USEC_PER_SEC);
01147
01148 return -1;
01149 }
01150
01151 if (!pid) {
01152 #ifdef HAVE_BINDPROCESSOR
01153
01154
01155
01156 int status = bindprocessor(BINDPROCESS, (int)getpid(),
01157 PROCESSOR_CLASS_ANY);
01158 if (status != OK)
01159 ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
01160 ap_server_conf,
01161 "processor unbind failed %d", status);
01162 #endif
01163 RAISE_SIGSTOP(MAKE_CHILD);
01164
01165 apr_signal(SIGTERM, just_die);
01166 child_main(slot);
01167
01168 clean_child_exit(0);
01169 }
01170
01171 ap_scoreboard_image->parent[slot].quiescing = 0;
01172 ap_scoreboard_image->parent[slot].pid = pid;
01173 return 0;
01174 }
01175
01176
01177 static void startup_children(int number_to_start)
01178 {
01179 int i;
01180
01181 for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
01182 if (ap_scoreboard_image->parent[i].pid != 0) {
01183 continue;
01184 }
01185 if (make_child(ap_server_conf, i) < 0) {
01186 break;
01187 }
01188 --number_to_start;
01189 }
01190 }
01191
01192
01193
01194
01195
01196
01197
01198
01199 static int idle_spawn_rate = 1;
01200 #ifndef MAX_SPAWN_RATE
01201 #define MAX_SPAWN_RATE (32)
01202 #endif
01203 static int hold_off_on_exponential_spawning;
01204
01205 static void perform_idle_server_maintenance(void)
01206 {
01207 int i, j;
01208 int idle_thread_count;
01209 worker_score *ws;
01210 process_score *ps;
01211 int free_length;
01212 int totally_free_length = 0;
01213 int free_slots[MAX_SPAWN_RATE];
01214 int last_non_dead;
01215 int total_non_dead;
01216
01217
01218 free_length = 0;
01219
01220 idle_thread_count = 0;
01221 last_non_dead = -1;
01222 total_non_dead = 0;
01223
01224 for (i = 0; i < ap_daemons_limit; ++i) {
01225
01226
01227 int status = SERVER_DEAD;
01228 int any_dying_threads = 0;
01229 int any_dead_threads = 0;
01230 int all_dead_threads = 1;
01231
01232 if (i >= ap_max_daemons_limit && totally_free_length == idle_spawn_rate)
01233 break;
01234 ps = &ap_scoreboard_image->parent[i];
01235 for (j = 0; j < ap_threads_per_child; j++) {
01236 ws = &ap_scoreboard_image->servers[i][j];
01237 status = ws->status;
01238
01239
01240 any_dying_threads = any_dying_threads ||
01241 (status == SERVER_GRACEFUL);
01242 any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
01243 all_dead_threads = all_dead_threads &&
01244 (status == SERVER_DEAD ||
01245 status == SERVER_GRACEFUL);
01246
01247
01248
01249
01250
01251
01252
01253 if (status <= SERVER_READY && status != SERVER_DEAD &&
01254 !ps->quiescing &&
01255 ps->generation == ap_my_generation &&
01256
01257
01258
01259 ps->pid != 0) {
01260 ++idle_thread_count;
01261 }
01262 }
01263 if (any_dead_threads && totally_free_length < idle_spawn_rate
01264 && (!ps->pid
01265 || ps->quiescing)) {
01266 if (all_dead_threads) {
01267
01268
01269
01270
01271
01272
01273
01274 free_slots[free_length] = free_slots[totally_free_length];
01275 free_slots[totally_free_length++] = i;
01276 }
01277 else {
01278
01279
01280 free_slots[free_length] = i;
01281 }
01282 ++free_length;
01283 }
01284
01285 if (!any_dying_threads) {
01286 last_non_dead = i;
01287 ++total_non_dead;
01288 }
01289 }
01290 ap_max_daemons_limit = last_non_dead + 1;
01291
01292 if (idle_thread_count > max_spare_threads) {
01293
01294 ap_mpm_pod_signal(pod);
01295 idle_spawn_rate = 1;
01296 }
01297 else if (idle_thread_count < min_spare_threads) {
01298
01299 if (free_length == 0) {
01300
01301 static int reported = 0;
01302
01303 if (!reported) {
01304 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
01305 ap_server_conf,
01306 "server reached MaxClients setting, consider"
01307 " raising the MaxClients setting");
01308 reported = 1;
01309 }
01310 idle_spawn_rate = 1;
01311 }
01312 else {
01313 if (free_length > idle_spawn_rate) {
01314 free_length = idle_spawn_rate;
01315 }
01316 if (idle_spawn_rate >= 8) {
01317 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
01318 ap_server_conf,
01319 "server seems busy, (you may need "
01320 "to increase StartServers, ThreadsPerChild "
01321 "or Min/MaxSpareThreads), "
01322 "spawning %d children, there are around %d idle "
01323 "threads, and %d total children", free_length,
01324 idle_thread_count, total_non_dead);
01325 }
01326 for (i = 0; i < free_length; ++i) {
01327 make_child(ap_server_conf, free_slots[i]);
01328 }
01329
01330
01331
01332 if (hold_off_on_exponential_spawning) {
01333 --hold_off_on_exponential_spawning;
01334 }
01335 else if (idle_spawn_rate < MAX_SPAWN_RATE) {
01336 idle_spawn_rate *= 2;
01337 }
01338 }
01339 }
01340 else {
01341 idle_spawn_rate = 1;
01342 }
01343 }
01344
01345 static void server_main_loop(int remaining_children_to_start)
01346 {
01347 int child_slot;
01348 apr_exit_why_e exitwhy;
01349 int status, processed_status;
01350 apr_proc_t pid;
01351 int i;
01352
01353 while (!restart_pending && !shutdown_pending) {
01354 ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
01355
01356 if (pid.pid != -1) {
01357 processed_status = ap_process_child_status(&pid, exitwhy, status);
01358 if (processed_status == APEXIT_CHILDFATAL) {
01359 shutdown_pending = 1;
01360 child_fatal = 1;
01361 return;
01362 }
01363
01364 child_slot = find_child_by_pid(&pid);
01365 if (child_slot >= 0) {
01366 for (i = 0; i < ap_threads_per_child; i++)
01367 ap_update_child_status_from_indexes(child_slot, i, SERVER_DEAD,
01368 (request_rec *) NULL);
01369
01370 ap_scoreboard_image->parent[child_slot].pid = 0;
01371 ap_scoreboard_image->parent[child_slot].quiescing = 0;
01372 if (processed_status == APEXIT_CHILDSICK) {
01373
01374 idle_spawn_rate = 1;
01375 }
01376 else if (remaining_children_to_start
01377 && child_slot < ap_daemons_limit) {
01378
01379
01380
01381 make_child(ap_server_conf, child_slot);
01382 --remaining_children_to_start;
01383 }
01384 #if APR_HAS_OTHER_CHILD
01385 }
01386 else if (apr_proc_other_child_read(&pid, status) == 0) {
01387
01388 #endif
01389 }
01390 else if (is_graceful) {
01391
01392
01393
01394 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
01395 ap_server_conf,
01396 "long lost child came home! (pid %ld)",
01397 (long)pid.pid);
01398 }
01399
01400
01401
01402
01403
01404 continue;
01405 }
01406 else if (remaining_children_to_start) {
01407
01408
01409
01410
01411 startup_children(remaining_children_to_start);
01412 remaining_children_to_start = 0;
01413
01414
01415
01416
01417 continue;
01418 }
01419
01420 perform_idle_server_maintenance();
01421 }
01422 }
01423
01424 int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
01425 {
01426 int remaining_children_to_start;
01427 apr_status_t rv;
01428
01429 ap_log_pid(pconf, ap_pid_fname);
01430
01431 first_server_limit = server_limit;
01432 first_thread_limit = thread_limit;
01433 if (changed_limit_at_restart) {
01434 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
01435 "WARNING: Attempt to change ServerLimit or ThreadLimit "
01436 "ignored during restart");
01437 changed_limit_at_restart = 0;
01438 }
01439
01440
01441 ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_PID_T_FMT,
01442 ap_server_root_relative(_pconf, ap_lock_fname),
01443