| 374 |
* child to force an exit) and so do an exit anyway. |
* child to force an exit) and so do an exit anyway. |
| 375 |
*/ |
*/ |
| 376 |
|
|
| 377 |
static void ap_start_shutdown(void) |
static void ap_start_shutdown(int graceful) |
| 378 |
{ |
{ |
| 379 |
mpm_state = AP_MPMQ_STOPPING; |
mpm_state = AP_MPMQ_STOPPING; |
| 380 |
if (shutdown_pending == 1) { |
if (shutdown_pending == 1) { |
| 385 |
return; |
return; |
| 386 |
} |
} |
| 387 |
shutdown_pending = 1; |
shutdown_pending = 1; |
| 388 |
|
is_graceful = graceful; |
| 389 |
} |
} |
| 390 |
|
|
| 391 |
/* do a graceful restart if graceful == 1 */ |
/* do a graceful restart if graceful == 1 */ |
| 402 |
|
|
| 403 |
static void sig_term(int sig) |
static void sig_term(int sig) |
| 404 |
{ |
{ |
| 405 |
ap_start_shutdown(); |
ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP); |
| 406 |
} |
} |
| 407 |
|
|
| 408 |
static void restart(int sig) |
static void restart(int sig) |
| 428 |
if (sigaction(SIGTERM, &sa, NULL) < 0) |
if (sigaction(SIGTERM, &sa, NULL) < 0) |
| 429 |
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, |
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, |
| 430 |
"sigaction(SIGTERM)"); |
"sigaction(SIGTERM)"); |
| 431 |
|
#ifdef AP_SIG_GRACEFUL_STOP |
| 432 |
|
if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0) |
| 433 |
|
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, |
| 434 |
|
"sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")"); |
| 435 |
|
#endif |
| 436 |
#ifdef SIGINT |
#ifdef SIGINT |
| 437 |
if (sigaction(SIGINT, &sa, NULL) < 0) |
if (sigaction(SIGINT, &sa, NULL) < 0) |
| 438 |
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, |
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, |
| 485 |
#ifdef AP_SIG_GRACEFUL |
#ifdef AP_SIG_GRACEFUL |
| 486 |
apr_signal(AP_SIG_GRACEFUL, restart); |
apr_signal(AP_SIG_GRACEFUL, restart); |
| 487 |
#endif /* AP_SIG_GRACEFUL */ |
#endif /* AP_SIG_GRACEFUL */ |
| 488 |
|
#ifdef AP_SIG_GRACEFUL_STOP |
| 489 |
|
apr_signal(AP_SIG_GRACEFUL_STOP, sig_term); |
| 490 |
|
#endif /* AP_SIG_GRACEFUL_STOP */ |
| 491 |
#ifdef SIGPIPE |
#ifdef SIGPIPE |
| 492 |
apr_signal(SIGPIPE, SIG_IGN); |
apr_signal(SIGPIPE, SIG_IGN); |
| 493 |
#endif /* SIGPIPE */ |
#endif /* SIGPIPE */ |
| 1723 |
server_main_loop(remaining_children_to_start); |
server_main_loop(remaining_children_to_start); |
| 1724 |
mpm_state = AP_MPMQ_STOPPING; |
mpm_state = AP_MPMQ_STOPPING; |
| 1725 |
|
|
| 1726 |
if (shutdown_pending) { |
if (shutdown_pending && !is_graceful) { |
| 1727 |
/* Time to gracefully shut down: |
/* Time to shut down: |
| 1728 |
* Kill child processes, tell them to call child_exit, etc... |
* Kill child processes, tell them to call child_exit, etc... |
|
* (By "gracefully" we don't mean graceful in the same sense as |
|
|
* "apachectl graceful" where we allow old connections to finish.) |
|
| 1729 |
*/ |
*/ |
| 1730 |
ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE); |
ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE); |
| 1731 |
ap_reclaim_child_processes(1); /* Start with SIGTERM */ |
ap_reclaim_child_processes(1); /* Start with SIGTERM */ |
| 1737 |
if ( pidfile != NULL && unlink(pidfile) == 0) |
if ( pidfile != NULL && unlink(pidfile) == 0) |
| 1738 |
ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
| 1739 |
ap_server_conf, |
ap_server_conf, |
| 1740 |
"removed PID file %s (pid=%ld)", |
"removed PID file %s (pid=%" APR_PID_T_FMT ")", |
| 1741 |
pidfile, (long)getpid()); |
pidfile, getpid()); |
| 1742 |
|
|
| 1743 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, |
| 1744 |
ap_server_conf, "caught SIGTERM, shutting down"); |
ap_server_conf, "caught SIGTERM, shutting down"); |
| 1745 |
} |
} |
| 1746 |
return 1; |
return 1; |
| 1747 |
|
} else if (shutdown_pending) { |
| 1748 |
|
/* Time to gracefully shut down: |
| 1749 |
|
* Kill child processes, tell them to call child_exit, etc... |
| 1750 |
|
*/ |
| 1751 |
|
int active_children; |
| 1752 |
|
int index; |
| 1753 |
|
apr_time_t cutoff = 0; |
| 1754 |
|
|
| 1755 |
|
/* Close our listeners, and then ask our children to do same */ |
| 1756 |
|
ap_close_listeners(); |
| 1757 |
|
ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE); |
| 1758 |
|
ap_relieve_child_processes(); |
| 1759 |
|
|
| 1760 |
|
if (!child_fatal) { |
| 1761 |
|
/* cleanup pid file on normal shutdown */ |
| 1762 |
|
const char *pidfile = NULL; |
| 1763 |
|
pidfile = ap_server_root_relative (pconf, ap_pid_fname); |
| 1764 |
|
if ( pidfile != NULL && unlink(pidfile) == 0) |
| 1765 |
|
ap_log_error(APLOG_MARK, APLOG_INFO, 0, |
| 1766 |
|
ap_server_conf, |
| 1767 |
|
"removed PID file %s (pid=%" APR_PID_T_FMT ")", |
| 1768 |
|
pidfile, getpid()); |
| 1769 |
|
|
| 1770 |
|
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, |
| 1771 |
|
ap_server_conf, "caught SIGTERM, shutting down"); |
| 1772 |
|
} |
| 1773 |
|
|
| 1774 |
|
/* Don't really exit until each child has finished */ |
| 1775 |
|
shutdown_pending = 0; |
| 1776 |
|
do { |
| 1777 |
|
/* Pause for a second */ |
| 1778 |
|
apr_sleep(apr_time_from_sec(1)); |
| 1779 |
|
|
| 1780 |
|
/* Relieve any children which have now exited */ |
| 1781 |
|
ap_relieve_child_processes(); |
| 1782 |
|
|
| 1783 |
|
active_children = 0; |
| 1784 |
|
for (index = 0; index < ap_daemons_limit; ++index) { |
| 1785 |
|
if (MPM_CHILD_PID(index) != 0) { |
| 1786 |
|
if (kill(MPM_CHILD_PID(index), 0) == 0) { |
| 1787 |
|
active_children = 1; |
| 1788 |
|
/* Having just one child is enough to stay around */ |
| 1789 |
|
break; |
| 1790 |
|
} |
| 1791 |
|
} |
| 1792 |
|
} |
| 1793 |
|
} while (!shutdown_pending && active_children && |
| 1794 |
|
(!ap_graceful_shutdown_timeout || apr_time_now() < cutoff)); |
| 1795 |
|
|
| 1796 |
|
/* We might be here because we received SIGTERM, either |
| 1797 |
|
* way, try and make sure that all of our processes are |
| 1798 |
|
* really dead. |
| 1799 |
|
*/ |
| 1800 |
|
ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE); |
| 1801 |
|
ap_reclaim_child_processes(1); |
| 1802 |
|
|
| 1803 |
|
return 1; |
| 1804 |
} |
} |
| 1805 |
|
|
| 1806 |
/* we've been told to restart */ |
/* we've been told to restart */ |
| 2214 |
"Maximum number of child processes for this run of Apache"), |
"Maximum number of child processes for this run of Apache"), |
| 2215 |
AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF, |
AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF, |
| 2216 |
"Maximum number of worker threads per child process for this run of Apache - Upper limit for ThreadsPerChild"), |
"Maximum number of worker threads per child process for this run of Apache - Upper limit for ThreadsPerChild"), |
| 2217 |
|
AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND, |
| 2218 |
{ NULL } |
{ NULL } |
| 2219 |
}; |
}; |
| 2220 |
|
|