📄 prefork.c
字号:
"caught SIGTERM, shutting down"); return 1; } else if (shutdown_pending) { /* Time to perform a graceful shut down: * Reap the inactive children, and ask the active ones * to close their listeners, then wait until they are * all done to exit. */ int active_children; apr_time_t cutoff = 0; /* Stop listening */ ap_close_listeners(); /* kill off the idle ones */ ap_mpm_pod_killpg(pod, ap_max_daemons_limit); /* Send SIGUSR1 to the active children */ active_children = 0; for (index = 0; index < ap_daemons_limit; ++index) { if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) { /* Ask each child to close its listeners. */ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL); active_children++; } } /* Allow each child which actually finished to exit */ ap_relieve_child_processes(); /* cleanup pid file */ { const char *pidfile = NULL; pidfile = ap_server_root_relative (pconf, ap_pid_fname); if ( pidfile != NULL && unlink(pidfile) == 0) ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, "removed PID file %s (pid=%ld)", pidfile, (long)getpid()); } ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "caught " AP_SIG_GRACEFUL_STOP_STRING ", shutting down gracefully"); if (ap_graceful_shutdown_timeout) { cutoff = apr_time_now() + apr_time_from_sec(ap_graceful_shutdown_timeout); } /* Don't really exit until each child has finished */ shutdown_pending = 0; do { /* Pause for a second */ sleep(1); /* Relieve any children which have now exited */ ap_relieve_child_processes(); active_children = 0; for (index = 0; index < ap_daemons_limit; ++index) { if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) { active_children = 1; /* Having just one child is enough to stay around */ break; } } } while (!shutdown_pending && active_children && (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff)); /* We might be here because we received SIGTERM, either * way, try and make sure that all of our processes are * really dead. */ unixd_killpg(getpgrp(), SIGTERM); return 1; } /* we've been told to restart */ apr_signal(SIGHUP, SIG_IGN); apr_signal(AP_SIG_GRACEFUL, SIG_IGN); if (one_process) { /* not worth thinking about */ return 1; } /* advance to the next generation */ /* XXX: we really need to make sure this new generation number isn't in * use by any of the children. */ ++ap_my_generation; ap_scoreboard_image->global->running_generation = ap_my_generation; if (is_graceful) { ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "Graceful restart requested, doing restart"); /* kill off the idle ones */ ap_mpm_pod_killpg(pod, ap_max_daemons_limit); /* This is mostly for debugging... so that we know what is still * gracefully dealing with existing request. This will break * in a very nasty way if we ever have the scoreboard totally * file-based (no shared memory) */ for (index = 0; index < ap_daemons_limit; ++index) { if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) { ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL; /* Ask each child to close its listeners. * * NOTE: we use the scoreboard, because if we send SIGUSR1 * to every process in the group, this may include CGI's, * piped loggers, etc. They almost certainly won't handle * it gracefully. */ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); } } } else { /* Kill 'em off */ if (unixd_killpg(getpgrp(), SIGHUP) < 0) { ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGHUP"); } ap_reclaim_child_processes(0); /* Not when just starting up */ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "SIGHUP received. Attempting to restart"); } return 0;}/* This really should be a post_config hook, but the error log is already * redirected by that point, so we need to do this in the open_logs phase. */static int prefork_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s){ apr_status_t rv; pconf = p; ap_server_conf = s; if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) { ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0, NULL, "no listening sockets available, shutting down"); return DONE; } if ((rv = ap_mpm_pod_open(pconf, &pod))) { ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_STARTUP, rv, NULL, "Could not open pipe-of-death."); return DONE; } return OK;}static int prefork_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp){ static int restart_num = 0; int no_detach, debug, foreground; apr_status_t rv; mpm_state = AP_MPMQ_STARTING; debug = ap_exists_config_define("DEBUG"); if (debug) { foreground = one_process = 1; no_detach = 0; } else { no_detach = ap_exists_config_define("NO_DETACH"); one_process = ap_exists_config_define("ONE_PROCESS"); foreground = ap_exists_config_define("FOREGROUND"); } /* sigh, want this only the second time around */ if (restart_num++ == 1) { is_graceful = 0; if (!one_process && !foreground) { rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND : APR_PROC_DETACH_DAEMONIZE); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, "apr_proc_detach failed"); return HTTP_INTERNAL_SERVER_ERROR; } } parent_pid = ap_my_pid = getpid(); } unixd_pre_config(ptemp); ap_listen_pre_config(); ap_daemons_to_start = DEFAULT_START_DAEMON; ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON; ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON; ap_daemons_limit = server_limit; ap_pid_fname = DEFAULT_PIDLOG; ap_lock_fname = DEFAULT_LOCKFILE; ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; ap_extended_status = 0;#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;#endif apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir)); return OK;}static void prefork_hooks(apr_pool_t *p){ /* The prefork open_logs phase must run before the core's, or stderr * will be redirected to a file, and the messages won't print to the * console. */ static const char *const aszSucc[] = {"core.c", NULL};#ifdef AUX3 (void) set42sig();#endif ap_hook_open_logs(prefork_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE); /* we need to set the MPM state before other pre-config hooks use MPM query * to retrieve it, so register as REALLY_FIRST */ ap_hook_pre_config(prefork_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);}static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg){ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } ap_daemons_to_start = atoi(arg); return NULL;}static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, const char *arg){ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } ap_daemons_min_free = atoi(arg); if (ap_daemons_min_free <= 0) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: detected MinSpareServers set to non-positive."); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "Resetting to 1 to avoid almost certain Apache failure."); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "Please read the documentation."); ap_daemons_min_free = 1; } return NULL;}static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, const char *arg){ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } ap_daemons_max_free = atoi(arg); return NULL;}static const char *set_max_clients (cmd_parms *cmd, void *dummy, const char *arg){ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } ap_daemons_limit = atoi(arg); if (ap_daemons_limit > server_limit) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: MaxClients of %d exceeds ServerLimit value " "of %d servers,", ap_daemons_limit, server_limit); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " lowering MaxClients to %d. To increase, please " "see the ServerLimit", server_limit); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " directive."); ap_daemons_limit = server_limit; } else if (ap_daemons_limit < 1) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: Require MaxClients > 0, setting to 1"); ap_daemons_limit = 1; } return NULL;}static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg){ int tmp_server_limit; const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } tmp_server_limit = atoi(arg); /* you cannot change ServerLimit across a restart; ignore * any such attempts */ if (first_server_limit && tmp_server_limit != server_limit) { /* how do we log a message? the error log is a bit bucket at this * point; we'll just have to set a flag so that ap_mpm_run() * logs a warning later */ changed_limit_at_restart = 1; return NULL; } server_limit = tmp_server_limit; if (server_limit > MAX_SERVER_LIMIT) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: ServerLimit of %d exceeds compile time limit " "of %d servers,", server_limit, MAX_SERVER_LIMIT); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " lowering ServerLimit to %d.", MAX_SERVER_LIMIT); server_limit = MAX_SERVER_LIMIT; } else if (server_limit < 1) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: Require ServerLimit > 0, setting to 1"); server_limit = 1; } return NULL;}static const command_rec prefork_cmds[] = {UNIX_DAEMON_COMMANDS,LISTEN_COMMANDS,AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF, "Number of child processes launched at server startup"),AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF, "Minimum number of idle children, to handle request spikes"),AP_INIT_TAKE1("MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF, "Maximum number of idle children"),AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF, "Maximum number of children alive at the same time"),AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF, "Maximum value of MaxClients for this run of Apache"),AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,{ NULL }};module AP_MODULE_DECLARE_DATA mpm_prefork_module = { MPM20_MODULE_STUFF, ap_mpm_rewrite_args, /* hook to run before apache parses args */ NULL, /* create per-directory config structure */ NULL, /* merge per-directory config structures */ NULL, /* create per-server config structure */ NULL, /* merge per-server config structures */ prefork_cmds, /* command apr_table_t */ prefork_hooks, /* register hooks */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -