From ba035df230e41bf9d70ebb47915c9472b7884412 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Jan 2011 22:55:54 +0100 Subject: [PATCH 1/1] execute: make sending of SIGKILL on shutdown optional --- TODO | 4 ---- man/systemd.mount.xml | 10 ++++++++++ man/systemd.service.xml | 20 +++++++++++++++++--- man/systemd.socket.xml | 11 +++++++++++ man/systemd.swap.xml | 11 +++++++++++ src/execute.c | 7 +++++-- src/execute.h | 1 + src/load-fragment.c | 1 + src/mount.c | 39 +++++++++++++++++++++++++++++++++------ src/service.c | 20 ++++++++++++++++---- src/service.h | 2 +- src/socket.c | 18 ++++++++++++++---- src/swap.c | 18 ++++++++++++++---- 13 files changed, 134 insertions(+), 28 deletions(-) diff --git a/TODO b/TODO index f87f7d118..4605115d0 100644 --- a/TODO +++ b/TODO @@ -4,8 +4,6 @@ * Fix multiple reload statements -* make usage of SIGKILL when shutting down services optional - * figure out what happened to bluez patch * in pam_systemd: add option to kill normal user sessions on logout but only those with uid != 0 @@ -23,8 +21,6 @@ * finish syslog socket stuff -* when starting systemd --user we get "Failed to set udev event buffer size." - * configurable jitter for timer events * dbus should run with oom adjust set diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index e2a9f2272..c7045e842 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -240,6 +240,16 @@ + + SendSIGKILL= + Specifies whether to + send SIGKILL to remaining processes + after a timeout, if the normal + shutdown procedure left processes of + the mount around. Takes a boolean + value. Defaults to "yes". + + diff --git a/man/systemd.service.xml b/man/systemd.service.xml index e5262f6d6..ee4d39375 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -560,14 +560,17 @@ . Processes will first be - terminated via SIGTERM (unless this is - changed via + terminated via SIGTERM (unless the + signal to send is changed via KillSignal=). If then after a delay (configured via the TimeoutSec= option) processes still remain, the termination request is repeated with - the SIGKILL signal. See + the SIGKILL signal (unless this is + disabled via the + SendSIGKILL= + option). See kill2 for more information. @@ -581,6 +584,17 @@ + + SendSIGKILL= + Specifies whether to + send SIGKILL to remaining processes + after a timeout, if the normal + shutdown procedure left processes of + the service around. Takes a boolean + value. Defaults to "yes". + + + NonBlocking= Set O_NONBLOCK flag diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 47ad91374..1aea2f89b 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -527,6 +527,17 @@ + + SendSIGKILL= + Specifies whether to + send SIGKILL to remaining processes + after a timeout, if the normal + shutdown procedure left processes of + the socket around. Takes a boolean + value. Defaults to "yes". + + + Service= Specifies the service diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml index 45467039e..45f8f40ae 100644 --- a/man/systemd.swap.xml +++ b/man/systemd.swap.xml @@ -176,6 +176,17 @@ swap. Defaults to SIGTERM. + + + SendSIGKILL= + Specifies whether to + send SIGKILL to remaining processes + after a timeout, if the normal + shutdown procedure left processes of + the swap around. Takes a boolean + value. Defaults to "yes". + + diff --git a/src/execute.c b/src/execute.c index 1e8dfaf77..10ce951c5 100644 --- a/src/execute.c +++ b/src/execute.c @@ -1349,6 +1349,7 @@ void exec_context_init(ExecContext *c) { c->syslog_level_prefix = true; c->mount_flags = MS_SHARED; c->kill_signal = SIGTERM; + c->send_sigkill = true; } void exec_context_done(ExecContext *c) { @@ -1618,9 +1619,11 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { fprintf(f, "%sKillMode: %s\n" - "%sKillSignal: SIG%s\n", + "%sKillSignal: SIG%s\n" + "%sSendSIGKILL: %s\n", prefix, kill_mode_to_string(c->kill_mode), - prefix, signal_to_string(c->kill_signal)); + prefix, signal_to_string(c->kill_signal), + prefix, yes_no(c->send_sigkill)); if (c->utmp_id) fprintf(f, diff --git a/src/execute.h b/src/execute.h index dd84c3d29..a6766f9e9 100644 --- a/src/execute.h +++ b/src/execute.h @@ -145,6 +145,7 @@ struct ExecContext { /* Not relevant for spawning processes, just for killing */ KillMode kill_mode; int kill_signal; + bool send_sigkill; cap_t capabilities; int secure_bits; diff --git a/src/load-fragment.c b/src/load-fragment.c index b7c3cbbc3..44b2cf06c 100644 --- a/src/load-fragment.c +++ b/src/load-fragment.c @@ -1820,6 +1820,7 @@ static int load_from_path(Unit *u, const char *path) { { "PAMName", config_parse_string_printf, &(context).pam_name, section }, \ { "KillMode", config_parse_kill_mode, &(context).kill_mode, section }, \ { "KillSignal", config_parse_kill_signal, &(context).kill_signal, section }, \ + { "SendSIGKILL", config_parse_bool, &(context).send_sigkill, section }, \ { "UtmpIdentifier", config_parse_string_printf, &(context).utmp_id, section } const ConfigItem items[] = { diff --git a/src/mount.c b/src/mount.c index 077ab9160..5b433c970 100644 --- a/src/mount.c +++ b/src/mount.c @@ -1156,18 +1156,45 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) { break; case MOUNT_MOUNTING_SIGTERM: - log_warning("%s mounting timed out. Killing.", u->meta.id); - mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, false); + if (m->exec_context.send_sigkill) { + log_warning("%s mounting timed out. Killing.", u->meta.id); + mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, false); + } else { + log_warning("%s mounting timed out. Skipping SIGKILL. Ignoring.", u->meta.id); + + if (m->from_proc_self_mountinfo) + mount_enter_mounted(m, false); + else + mount_enter_dead(m, false); + } break; case MOUNT_REMOUNTING_SIGTERM: - log_warning("%s remounting timed out. Killing.", u->meta.id); - mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, false); + if (m->exec_context.send_sigkill) { + log_warning("%s remounting timed out. Killing.", u->meta.id); + mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, false); + } else { + log_warning("%s remounting timed out. Skipping SIGKILL. Ignoring.", u->meta.id); + + if (m->from_proc_self_mountinfo) + mount_enter_mounted(m, false); + else + mount_enter_dead(m, false); + } break; case MOUNT_UNMOUNTING_SIGTERM: - log_warning("%s unmounting timed out. Killing.", u->meta.id); - mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, false); + if (m->exec_context.send_sigkill) { + log_warning("%s unmounting timed out. Killing.", u->meta.id); + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, false); + } else { + log_warning("%s unmounting timed out. Skipping SIGKILL. Ignoring.", u->meta.id); + + if (m->from_proc_self_mountinfo) + mount_enter_mounted(m, false); + else + mount_enter_dead(m, false); + } break; case MOUNT_MOUNTING_SIGKILL: diff --git a/src/service.c b/src/service.c index e4dfa4031..e765004e4 100644 --- a/src/service.c +++ b/src/service.c @@ -2712,8 +2712,14 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) { break; case SERVICE_STOP_SIGTERM: - log_warning("%s stopping timed out. Killing.", u->meta.id); - service_enter_signal(s, SERVICE_STOP_SIGKILL, false); + if (s->exec_context.send_sigkill) { + log_warning("%s stopping timed out. Killing.", u->meta.id); + service_enter_signal(s, SERVICE_STOP_SIGKILL, false); + } else { + log_warning("%s stopping timed out. Skipping SIGKILL.", u->meta.id); + service_enter_stop_post(s, false); + } + break; case SERVICE_STOP_SIGKILL: @@ -2731,8 +2737,14 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) { break; case SERVICE_FINAL_SIGTERM: - log_warning("%s stopping timed out (2). Killing.", u->meta.id); - service_enter_signal(s, SERVICE_FINAL_SIGKILL, false); + if (s->exec_context.send_sigkill) { + log_warning("%s stopping timed out (2). Killing.", u->meta.id); + service_enter_signal(s, SERVICE_FINAL_SIGKILL, false); + } else { + log_warning("%s stopping timed out (2). Skipping SIGKILL. Entering failed mode.", u->meta.id); + service_enter_dead(s, false, true); + } + break; case SERVICE_FINAL_SIGKILL: diff --git a/src/service.h b/src/service.h index 500bebff0..1b59dad93 100644 --- a/src/service.h +++ b/src/service.h @@ -33,7 +33,7 @@ typedef enum ServiceState { SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, - SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true, ehnce this is OK */ + SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */ SERVICE_RELOAD, SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */ SERVICE_STOP_SIGTERM, diff --git a/src/socket.c b/src/socket.c index cb38ab3d6..6ec49de46 100644 --- a/src/socket.c +++ b/src/socket.c @@ -1688,8 +1688,13 @@ static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) { break; case SOCKET_STOP_PRE_SIGTERM: - log_warning("%s stopping timed out. Killing.", u->meta.id); - socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, false); + if (s->exec_context.send_sigkill) { + log_warning("%s stopping timed out. Killing.", u->meta.id); + socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, false); + } else { + log_warning("%s stopping timed out. Skipping SIGKILL. Ignoring.", u->meta.id); + socket_enter_stop_post(s, false); + } break; case SOCKET_STOP_PRE_SIGKILL: @@ -1703,8 +1708,13 @@ static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) { break; case SOCKET_FINAL_SIGTERM: - log_warning("%s stopping timed out (2). Killing.", u->meta.id); - socket_enter_signal(s, SOCKET_FINAL_SIGKILL, false); + if (s->exec_context.send_sigkill) { + log_warning("%s stopping timed out (2). Killing.", u->meta.id); + socket_enter_signal(s, SOCKET_FINAL_SIGKILL, false); + } else { + log_warning("%s stopping timed out (2). Skipping SIGKILL. Ignoring.", u->meta.id); + socket_enter_dead(s, false); + } break; case SOCKET_FINAL_SIGKILL: diff --git a/src/swap.c b/src/swap.c index 0d3cb2f40..9bdb5aabf 100644 --- a/src/swap.c +++ b/src/swap.c @@ -995,13 +995,23 @@ static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) { break; case SWAP_ACTIVATING_SIGTERM: - log_warning("%s activation timed out. Killing.", u->meta.id); - swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, false); + if (s->exec_context.send_sigkill) { + log_warning("%s activation timed out. Killing.", u->meta.id); + swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, false); + } else { + log_warning("%s activation timed out. Skipping SIGKILL. Ignoring.", u->meta.id); + swap_enter_dead(s, false); + } break; case SWAP_DEACTIVATING_SIGTERM: - log_warning("%s deactivation timed out. Killing.", u->meta.id); - swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, false); + if (s->exec_context.send_sigkill) { + log_warning("%s deactivation timed out. Killing.", u->meta.id); + swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, false); + } else { + log_warning("%s deactivation timed out. Skipping SIGKILL. Ignoring.", u->meta.id); + swap_enter_dead(s, false); + } break; case SWAP_ACTIVATING_SIGKILL: -- 2.30.2