execute: make sending of SIGKILL on shutdown optional

This commit is contained in:
Lennart Poettering 2011-01-18 22:55:54 +01:00
parent 0058d7b91c
commit ba035df230
13 changed files with 134 additions and 28 deletions

4
TODO
View File

@ -4,8 +4,6 @@
* Fix multiple reload statements * Fix multiple reload statements
* make usage of SIGKILL when shutting down services optional
* figure out what happened to bluez patch * 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 * 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 * finish syslog socket stuff
* when starting systemd --user we get "Failed to set udev event buffer size."
* configurable jitter for timer events * configurable jitter for timer events
* dbus should run with oom adjust set * dbus should run with oom adjust set

View File

@ -240,6 +240,16 @@
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>SendSIGKILL=</varname></term>
<listitem><para>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".
</para></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -560,14 +560,17 @@
<option>control-group</option>.</para> <option>control-group</option>.</para>
<para>Processes will first be <para>Processes will first be
terminated via SIGTERM (unless this is terminated via SIGTERM (unless the
changed via signal to send is changed via
<varname>KillSignal=</varname>). If <varname>KillSignal=</varname>). If
then after a delay (configured via the then after a delay (configured via the
<varname>TimeoutSec=</varname> option) <varname>TimeoutSec=</varname> option)
processes still remain, the processes still remain, the
termination request is repeated with termination request is repeated with
the SIGKILL signal. See the SIGKILL signal (unless this is
disabled via the
<varname>SendSIGKILL=</varname>
option). See
<citerefentry><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry> <citerefentry><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for more for more
information.</para></listitem> information.</para></listitem>
@ -581,6 +584,17 @@
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>SendSIGKILL=</varname></term>
<listitem><para>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".
</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>NonBlocking=</varname></term> <term><varname>NonBlocking=</varname></term>
<listitem><para>Set O_NONBLOCK flag <listitem><para>Set O_NONBLOCK flag

View File

@ -527,6 +527,17 @@
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>SendSIGKILL=</varname></term>
<listitem><para>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".
</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>Service=</varname></term> <term><varname>Service=</varname></term>
<listitem><para>Specifies the service <listitem><para>Specifies the service

View File

@ -176,6 +176,17 @@
swap. Defaults to SIGTERM. swap. Defaults to SIGTERM.
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>SendSIGKILL=</varname></term>
<listitem><para>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".
</para></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -1349,6 +1349,7 @@ void exec_context_init(ExecContext *c) {
c->syslog_level_prefix = true; c->syslog_level_prefix = true;
c->mount_flags = MS_SHARED; c->mount_flags = MS_SHARED;
c->kill_signal = SIGTERM; c->kill_signal = SIGTERM;
c->send_sigkill = true;
} }
void exec_context_done(ExecContext *c) { void exec_context_done(ExecContext *c) {
@ -1618,9 +1619,11 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
fprintf(f, fprintf(f,
"%sKillMode: %s\n" "%sKillMode: %s\n"
"%sKillSignal: SIG%s\n", "%sKillSignal: SIG%s\n"
"%sSendSIGKILL: %s\n",
prefix, kill_mode_to_string(c->kill_mode), 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) if (c->utmp_id)
fprintf(f, fprintf(f,

View File

@ -145,6 +145,7 @@ struct ExecContext {
/* Not relevant for spawning processes, just for killing */ /* Not relevant for spawning processes, just for killing */
KillMode kill_mode; KillMode kill_mode;
int kill_signal; int kill_signal;
bool send_sigkill;
cap_t capabilities; cap_t capabilities;
int secure_bits; int secure_bits;

View File

@ -1820,6 +1820,7 @@ static int load_from_path(Unit *u, const char *path) {
{ "PAMName", config_parse_string_printf, &(context).pam_name, section }, \ { "PAMName", config_parse_string_printf, &(context).pam_name, section }, \
{ "KillMode", config_parse_kill_mode, &(context).kill_mode, section }, \ { "KillMode", config_parse_kill_mode, &(context).kill_mode, section }, \
{ "KillSignal", config_parse_kill_signal, &(context).kill_signal, 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 } { "UtmpIdentifier", config_parse_string_printf, &(context).utmp_id, section }
const ConfigItem items[] = { const ConfigItem items[] = {

View File

@ -1156,18 +1156,45 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
break; break;
case MOUNT_MOUNTING_SIGTERM: case MOUNT_MOUNTING_SIGTERM:
log_warning("%s mounting timed out. Killing.", u->meta.id); if (m->exec_context.send_sigkill) {
mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, false); 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; break;
case MOUNT_REMOUNTING_SIGTERM: case MOUNT_REMOUNTING_SIGTERM:
log_warning("%s remounting timed out. Killing.", u->meta.id); if (m->exec_context.send_sigkill) {
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, false); 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; break;
case MOUNT_UNMOUNTING_SIGTERM: case MOUNT_UNMOUNTING_SIGTERM:
log_warning("%s unmounting timed out. Killing.", u->meta.id); if (m->exec_context.send_sigkill) {
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, false); 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; break;
case MOUNT_MOUNTING_SIGKILL: case MOUNT_MOUNTING_SIGKILL:

View File

@ -2712,8 +2712,14 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
break; break;
case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGTERM:
log_warning("%s stopping timed out. Killing.", u->meta.id); if (s->exec_context.send_sigkill) {
service_enter_signal(s, SERVICE_STOP_SIGKILL, false); 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; break;
case SERVICE_STOP_SIGKILL: case SERVICE_STOP_SIGKILL:
@ -2731,8 +2737,14 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
break; break;
case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGTERM:
log_warning("%s stopping timed out (2). Killing.", u->meta.id); if (s->exec_context.send_sigkill) {
service_enter_signal(s, SERVICE_FINAL_SIGKILL, false); 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; break;
case SERVICE_FINAL_SIGKILL: case SERVICE_FINAL_SIGKILL:

View File

@ -33,7 +33,7 @@ typedef enum ServiceState {
SERVICE_START, SERVICE_START,
SERVICE_START_POST, SERVICE_START_POST,
SERVICE_RUNNING, 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_RELOAD,
SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */ SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */
SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGTERM,

View File

@ -1688,8 +1688,13 @@ static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
break; break;
case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGTERM:
log_warning("%s stopping timed out. Killing.", u->meta.id); if (s->exec_context.send_sigkill) {
socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, false); 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; break;
case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_PRE_SIGKILL:
@ -1703,8 +1708,13 @@ static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
break; break;
case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGTERM:
log_warning("%s stopping timed out (2). Killing.", u->meta.id); if (s->exec_context.send_sigkill) {
socket_enter_signal(s, SOCKET_FINAL_SIGKILL, false); 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; break;
case SOCKET_FINAL_SIGKILL: case SOCKET_FINAL_SIGKILL:

View File

@ -995,13 +995,23 @@ static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
break; break;
case SWAP_ACTIVATING_SIGTERM: case SWAP_ACTIVATING_SIGTERM:
log_warning("%s activation timed out. Killing.", u->meta.id); if (s->exec_context.send_sigkill) {
swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, false); 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; break;
case SWAP_DEACTIVATING_SIGTERM: case SWAP_DEACTIVATING_SIGTERM:
log_warning("%s deactivation timed out. Killing.", u->meta.id); if (s->exec_context.send_sigkill) {
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, false); 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; break;
case SWAP_ACTIVATING_SIGKILL: case SWAP_ACTIVATING_SIGKILL: