diff options
-rw-r--r-- | server/mpm/beos/beos.c | 241 |
1 files changed, 136 insertions, 105 deletions
diff --git a/server/mpm/beos/beos.c b/server/mpm/beos/beos.c index d0d8ed4705..067573b266 100644 --- a/server/mpm/beos/beos.c +++ b/server/mpm/beos/beos.c @@ -89,15 +89,13 @@ * Actual definitions of config globals */ -int ap_threads_per_child=0; /* Worker threads per child */ +int ap_threads_per_child=HARD_THREAD_LIMIT; /* Worker threads per child */ int ap_max_requests_per_child=0; static const char *ap_pid_fname=NULL; -static const char *ap_scoreboard_fname=NULL; static int ap_threads_to_start=0; static int min_spare_threads=0; static int max_spare_threads=0; static int ap_thread_limit=0; -AP_DECLARE_DATA int ap_extended_status = 0; static int num_listening_sockets = 0; /* set by open_listeners in ap_mpm_run */ static apr_socket_t ** listening_sockets; apr_lock_t *accept_mutex = NULL; @@ -117,8 +115,6 @@ typedef struct { apr_pool_t *tpool; } proc_info; -struct ap_ctable ap_child_table[HARD_SERVER_LIMIT]; - /* * The max child slot ever assigned, preserved across restarts. Necessary * to deal with MaxClients changes across SIGWINCH restarts. We use this @@ -127,7 +123,11 @@ struct ap_ctable ap_child_table[HARD_SERVER_LIMIT]; int ap_max_child_assigned = -1; int ap_max_threads_limit = -1; char ap_coredump_dir[MAX_STRING_LEN]; + + static volatile bool flag_of_death; +static int udp_sock; +static struct sockaddr_in udpsi; /* shared http_main globals... */ @@ -177,6 +177,7 @@ static void sig_coredump(int sig) static int volatile shutdown_pending; static int volatile restart_pending; static int volatile is_graceful; +ap_generation_t volatile ap_my_generation = 0; /* * ap_start_shutdown() and ap_start_restart(), below, are a first stab at @@ -219,6 +220,9 @@ static void ap_start_restart(int graceful) } restart_pending = 1; is_graceful = graceful; + if (is_graceful){ + apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard); + } } static void sig_term(int sig) @@ -234,14 +238,7 @@ static void restart(int sig) static void tell_workers_to_exit(void) { flag_of_death = true; -} - -static void push_workers_off_cliff(int sig) -{ - int i; - - for (i=0;i<ap_max_child_assigned;i++) - kill(ap_child_table[i].pid, sig); + sendto(udp_sock, "die!", 4, 0, (struct sockaddr*)&udpsi, sizeof(udpsi)); } static void set_signals(void) @@ -314,8 +311,9 @@ static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num) apr_socket_close(sock); return; } - + current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id); + if (current_conn) { ap_process_connection(current_conn); ap_lingering_close(current_conn); @@ -350,8 +348,11 @@ static int32 worker_thread(void * dummy) worker_thread_count++; apr_lock_release(worker_thread_count_mutex); + (void) ap_update_child_status(0, child_slot, SERVER_STARTING, + (request_rec*)NULL); + apr_poll_setup(&pollset, num_listening_sockets, tpool); - for(n=0 ; n < num_listening_sockets ; ++n) + for(n=0 ; n <= num_listening_sockets ; ++n) apr_poll_socket_add(pollset, listening_sockets[n], APR_POLLIN); while (!this_worker_should_exit) { @@ -359,6 +360,9 @@ static int32 worker_thread(void * dummy) if (this_worker_should_exit) break; + (void) ap_update_child_status(0, child_slot, SERVER_READY, + (request_rec*)NULL); + apr_lock_aquire(accept_mutex); while (!this_worker_should_exit) { apr_int16_t event; @@ -367,6 +371,10 @@ static int32 worker_thread(void * dummy) if (flag_of_death) this_worker_should_exit = 1; + apr_poll_revents_get(&event, listening_sockets[0], pollset); + if (event & APR_POLLIN) + this_worker_should_exit = 1; + if (ret != APR_SUCCESS) { if (errno == EINTR) { continue; @@ -423,14 +431,10 @@ static int32 worker_thread(void * dummy) apr_clear_pool(ptrans); } - apr_pool_destroy(tpool); + ap_update_child_status(0, child_slot, SERVER_DEAD, (request_rec*)NULL); + apr_lock_aquire(worker_thread_count_mutex); worker_thread_count--; - if (worker_thread_count == 0) { - /* All the threads have exited, now finish the shutdown process - * by signalling the sigwait thread */ - kill(server_pid, SIGTERM); - } apr_lock_release(worker_thread_count_mutex); return (0); @@ -439,7 +443,7 @@ static int32 worker_thread(void * dummy) static int make_worker(server_rec *s, int slot) { thread_id tid; - proc_info *my_info = (proc_info *)malloc(sizeof(proc_info)); + proc_info *my_info = (proc_info *)malloc(sizeof(proc_info)); /* freed by thread... */ if (my_info == NULL) { ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf, @@ -455,11 +459,11 @@ static int make_worker(server_rec *s, int slot) if (one_process) { set_signals(); - ap_child_table[slot].pid = getpid(); - ap_child_table[slot].status = SERVER_ALIVE; + ap_scoreboard_image->parent[0].pid = getpid(); return 0; } + (void) ap_update_child_status(0, slot, SERVER_STARTING, (request_rec*)NULL); tid = spawn_thread(worker_thread, "apache_worker", B_NORMAL_PRIORITY, my_info); if (tid < B_NO_ERROR) { @@ -468,14 +472,17 @@ static int make_worker(server_rec *s, int slot) /* In case system resources are maxxed out, we don't want * Apache running away with the CPU trying to fork over and * over and over again. */ + (void) ap_update_child_status(0, slot, SERVER_DEAD, + (request_rec*)NULL); + sleep(10); - + free(my_info); + return -1; } resume_thread(tid); - - ap_child_table[slot].pid = tid; - ap_child_table[slot].status = SERVER_ALIVE; + + ap_scoreboard_image->servers[0][slot].tid = tid; return 0; } @@ -484,8 +491,11 @@ static void startup_threads(int number_to_start) { int i; + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "starting %d threads", number_to_start); + for (i = 0; number_to_start && i < ap_thread_limit; ++i) { - if (ap_child_table[i].pid) { + if (ap_scoreboard_image->servers[0][i].tid) { continue; } if (make_worker(ap_server_conf, i) < 0) { @@ -519,7 +529,7 @@ static void perform_idle_server_maintenance(void) free_length = 0; for (i = 0; i < ap_thread_limit; ++i) { - if (ap_child_table[i].pid == 0) { + if (ap_scoreboard_image->servers[0][i].tid == 0) { if (free_length < spawn_rate) { free_slots[free_length] = i; ++free_length; @@ -567,75 +577,89 @@ static void server_main_loop(int remaining_threads_to_start) /* non-fatal death... note that it's gone in the scoreboard. */ child_slot = -1; for (i = 0; i < ap_max_child_assigned; ++i) { - if (ap_child_table[i].pid == pid.pid) { - int j; - + if (ap_scoreboard_image->servers[0][i].tid == pid.pid) { child_slot = i; - for (j = 0; j < HARD_THREAD_LIMIT; j++) { - ap_beos_force_reset_connection_status(i * HARD_THREAD_LIMIT + j); - } break; } } if (child_slot >= 0) { - ap_child_table[child_slot].pid = 0; + ap_scoreboard_image->servers[0][child_slot].tid = 0; + (void) ap_update_child_status(0, child_slot, SERVER_DEAD, (request_rec*)NULL); - if (remaining_threads_to_start - && child_slot < ap_thread_limit) { - /* we're still doing a 1-for-1 replacement of dead + if (remaining_threads_to_start + && child_slot < ap_thread_limit) { + /* we're still doing a 1-for-1 replacement of dead * children with new children */ - make_worker(ap_server_conf, child_slot); - --remaining_threads_to_start; - } + make_worker(ap_server_conf, child_slot); + --remaining_threads_to_start; + } #if APR_HAS_OTHER_CHILD - } - else if (apr_proc_other_child_read(&pid, status) == 0) { - /* handled */ + } + else if (apr_proc_other_child_read(&pid, status) == 0) { + /* handled */ #endif - } - else if (is_graceful) { - /* Great, we've probably just lost a slot in the - * scoreboard. Somehow we don't know about this - * child. - */ - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, ap_server_conf, - "long lost child came home! (pid %ld)", pid.pid); - } + } + else if (is_graceful) { + /* Great, we've probably just lost a slot in the + * scoreboard. Somehow we don't know about this + * child. + */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, ap_server_conf, + "long lost child came home! (pid %ld)", pid.pid); + } - /* Don't perform idle maintenance when a child dies, - * only do it when there's a timeout. Remember only a - * finite number of children can die, and it's pretty - * pathological for a lot to die suddenly. - */ - continue; - } - else if (remaining_threads_to_start) { - /* we hit a 1 second timeout in which none of the previous - * generation of children needed to be reaped... so assume - * they're all done, and pick up the slack if any is left. - */ - startup_threads(remaining_threads_to_start); - remaining_threads_to_start = 0; - /* In any event we really shouldn't do the code below because - * few of the servers we just started are in the IDLE state - * yet, so we'd mistakenly create an extra server. - */ - continue; - } - - perform_idle_server_maintenance(); + /* Don't perform idle maintenance when a child dies, + * only do it when there's a timeout. Remember only a + * finite number of children can die, and it's pretty + * pathological for a lot to die suddenly. + */ + continue; + } + else if (remaining_threads_to_start) { + /* we hit a 1 second timeout in which none of the previous + * generation of children needed to be reaped... so assume + * they're all done, and pick up the slack if any is left. + */ + startup_threads(remaining_threads_to_start); + remaining_threads_to_start = 0; + /* In any event we really shouldn't do the code below because + * few of the servers we just started are in the IDLE state + * yet, so we'd mistakenly create an extra server. + */ + continue; + } + perform_idle_server_maintenance(); } } int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) { - int remaining_threads_to_start, i; + int remaining_threads_to_start, i,j; apr_status_t rv; ap_listen_rec *lr; pconf = _pconf; ap_server_conf = s; - + + ap_scoreboard_fname = DEFAULT_SCOREBOARD; + + if ((udp_sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0){ + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, s, + "couldn't create control socket, shutting down"); + return 1; + } + + /* now build the udp sockaddr_in structure... */ + udpsi.sin_len = sizeof(struct sockaddr_in); + udpsi.sin_family = AF_INET; + udpsi.sin_port = htons(7777); + udpsi.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if (bind(udp_sock, (struct sockaddr*)&udpsi, sizeof(udpsi)) < 0){ + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, s, + "couldn't bind the control socket, shutting down"); + return 1; + } + if ((num_listening_sockets = ap_setup_listeners(ap_server_conf)) < 1) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s, "no listening sockets available, shutting down"); @@ -643,7 +667,6 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) } ap_log_pid(pconf, ap_pid_fname); - flag_of_death = false; /* @@ -662,6 +685,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) "Couldn't create accept lock"); return 1; } + /* worker_thread_count_mutex * locks the worker_thread_count so we have ana ccurate count... */ @@ -679,8 +703,19 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) if (!is_graceful) ap_create_scoreboard(pconf, SB_SHARED); + if (!is_graceful) { + for (i = 0; i < HARD_SERVER_LIMIT; i++) { + ap_scoreboard_image->parent[i].pid = 0; + for (j = 0;j < HARD_THREAD_LIMIT; j++) + ap_scoreboard_image->servers[i][j].tid = 0; + } + } + if (HARD_SERVER_LIMIT == 1) + ap_scoreboard_image->parent[0].pid = getpid(); + set_signals(); - /* Sanity cehcks to avoid thrashing... */ + + /* Sanity checks to avoid thrashing... */ if (max_spare_threads < min_spare_threads ) max_spare_threads = min_spare_threads; @@ -708,8 +743,11 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) * the listenfds and creat the pollset... */ listening_sockets = apr_palloc(pchild, - sizeof(*listening_sockets) * (num_listening_sockets)); - for (lr = ap_listeners, i = 0; i < num_listening_sockets; lr = lr->next, ++i) + sizeof(*listening_sockets) * (num_listening_sockets + 1)); + + apr_os_sock_put(&listening_sockets[0], &udp_sock, pchild); + + for (lr = ap_listeners, i = 1; i <= num_listening_sockets; lr = lr->next, ++i) listening_sockets[i]=lr->sd; /* we assume all goes OK...hmm might want to check that! */ @@ -729,15 +767,23 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf, "%s configured -- resuming normal operations", ap_get_server_version()); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf, "Server built: %s", ap_get_server_built()); + restart_pending = shutdown_pending = 0; /* * main_loop until it's all over */ server_main_loop(remaining_threads_to_start); + + tell_workers_to_exit(); /* if we get here we're exiting... */ + sleep(1); /* give them a brief chance to exit */ + /* close the UDP socket we've been using... */ + apr_socket_close(listening_sockets[0]); + /* * If we get here we're shutting down... */ @@ -767,7 +813,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf, "caught SIGTERM, shutting down"); - return 1; + return 1; } /* we've been told to restart */ @@ -780,15 +826,12 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) if (is_graceful) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf, "SIGWINCH received. Doing graceful restart"); - tell_workers_to_exit(); - /* TODO - need to test some ideas here... */ } else { /* Kill 'em all. Since the child acts the same on the parents SIGTERM * and a SIGHUP, we may as well use the same signal, because some user * pthreads are stealing signals from us left and right. */ - push_workers_off_cliff(SIGTERM); ap_reclaim_child_processes(1); /* Start with SIGTERM */ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf, @@ -814,21 +857,23 @@ static void beos_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *pte /* sigh, want this only the second time around */ if (restart_num++ == 1) { is_graceful = 0; + if (!one_process && !no_detach) apr_proc_detach(); + server_pid = getpid(); } beosd_pre_config(); ap_listen_pre_config(); ap_threads_to_start = DEFAULT_START_THREADS; - min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD; - max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD; - ap_thread_limit = HARD_SERVER_LIMIT; + min_spare_threads = DEFAULT_MIN_FREE_THREADS; + max_spare_threads = DEFAULT_MAX_FREE_THREADS; + ap_thread_limit = HARD_THREAD_LIMIT; ap_threads_per_child = DEFAULT_THREADS_PER_CHILD; ap_pid_fname = DEFAULT_PIDLOG; + ap_scoreboard_fname = DEFAULT_SCOREBOARD; ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; - ap_beos_set_maintain_connection_status(1); apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir)); } @@ -975,18 +1020,6 @@ static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg return NULL; } -static const char *set_maintain_connection_status(cmd_parms *cmd, - void *dummy, int arg) -{ - const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err != NULL) { - return err; - } - - ap_beos_set_maintain_connection_status(arg != 0); - return NULL; -} - static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, const char *arg) { apr_finfo_t finfo; @@ -1024,8 +1057,6 @@ AP_INIT_TAKE1( "ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF, "Number of threads each child creates" ), AP_INIT_TAKE1( "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, "Maximum number of requests a particular child serves before dying." ), -AP_INIT_FLAG( "ConnectionStatus", set_maintain_connection_status, NULL, RSRC_CONF, - "Whether or not to maintain status information on current connections." ), AP_INIT_TAKE1( "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, "The location of the directory Apache changes to before dumping core" ), { NULL } |