1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-07 09:56:51 +03:00

shutdown: make kill timeout configurable (#7835)

By default systemd-shutdown will wait for 90s after SIGTERM was sent
for all processes to exit. This is way too long and effectively defeats
an emergency watchdog reboot via "reboot-force" actions. Instead now
use DefaultTimeoutStopSec which is configurable.
This commit is contained in:
Jan Klötzke 2018-01-10 19:00:20 +01:00 committed by Lennart Poettering
parent 0a7eed95dd
commit e73c54b838
4 changed files with 26 additions and 11 deletions

View File

@ -89,7 +89,7 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) {
return true;
}
static void wait_for_children(Set *pids, sigset_t *mask) {
static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
usec_t until;
assert(mask);
@ -97,7 +97,7 @@ static void wait_for_children(Set *pids, sigset_t *mask) {
if (set_isempty(pids))
return;
until = now(CLOCK_MONOTONIC) + DEFAULT_TIMEOUT_USEC;
until = now(CLOCK_MONOTONIC) + timeout;
for (;;) {
struct timespec ts;
int k;
@ -221,7 +221,7 @@ static int killall(int sig, Set *pids, bool send_sighup) {
return set_size(pids);
}
void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup) {
void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout) {
sigset_t mask, oldmask;
_cleanup_set_free_ Set *pids = NULL;
@ -241,7 +241,7 @@ void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup) {
log_warning_errno(errno, "kill(-1, SIGCONT) failed: %m");
if (wait_for_exit)
wait_for_children(pids, &mask);
wait_for_children(pids, &mask, timeout);
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
}

View File

@ -20,4 +20,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup);
#include "time-util.h"
void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout);

View File

@ -1467,17 +1467,19 @@ static int become_shutdown(
int retval) {
char log_level[DECIMAL_STR_MAX(int) + 1],
exit_code[DECIMAL_STR_MAX(uint8_t) + 1];
exit_code[DECIMAL_STR_MAX(uint8_t) + 1],
timeout[DECIMAL_STR_MAX(usec_t) + 1];
const char* command_line[11] = {
const char* command_line[13] = {
SYSTEMD_SHUTDOWN_BINARY_PATH,
shutdown_verb,
"--timeout", timeout,
"--log-level", log_level,
"--log-target",
};
_cleanup_strv_free_ char **env_block = NULL;
size_t pos = 5;
size_t pos = 7;
int r;
assert(shutdown_verb);
@ -1485,6 +1487,7 @@ static int become_shutdown(
env_block = strv_copy(environ);
xsprintf(log_level, "%d", log_get_max_level());
xsprintf(timeout, "%" PRI_USEC "us", arg_default_timeout_stop_usec);
switch (log_get_target()) {
@ -1640,7 +1643,7 @@ static void do_reexecute(
if (switch_root_dir) {
/* Kill all remaining processes from the initrd, but don't wait for them, so that we can handle the
* SIGCHLD for them after deserializing. */
broadcast_signal(SIGTERM, false, true);
broadcast_signal(SIGTERM, false, true, arg_default_timeout_stop_usec);
/* And switch root with MS_MOVE, because we remove the old directory afterwards and detach it. */
r = switch_root(switch_root_dir, "/mnt", true, MS_MOVE);

View File

@ -58,6 +58,7 @@
static char* arg_verb;
static uint8_t arg_exit_code;
static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
static int parse_argv(int argc, char *argv[]) {
enum {
@ -66,6 +67,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_LOG_COLOR,
ARG_LOG_LOCATION,
ARG_EXIT_CODE,
ARG_TIMEOUT,
};
static const struct option options[] = {
@ -74,6 +76,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "log-color", optional_argument, NULL, ARG_LOG_COLOR },
{ "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
{ "exit-code", required_argument, NULL, ARG_EXIT_CODE },
{ "timeout", required_argument, NULL, ARG_TIMEOUT },
{}
};
@ -129,6 +132,13 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_TIMEOUT:
r = parse_sec(optarg, &arg_timeout);
if (r < 0)
log_error("Failed to parse shutdown timeout %s, ignoring", optarg);
break;
case '\001':
if (!arg_verb)
arg_verb = optarg;
@ -327,10 +337,10 @@ int main(int argc, char *argv[]) {
disable_core_dumps();
log_info("Sending SIGTERM to remaining processes...");
broadcast_signal(SIGTERM, true, true);
broadcast_signal(SIGTERM, true, true, arg_timeout);
log_info("Sending SIGKILL to remaining processes...");
broadcast_signal(SIGKILL, true, false);
broadcast_signal(SIGKILL, true, false, arg_timeout);
need_umount = !in_container;
need_swapoff = !in_container;