mirror of
https://github.com/systemd/systemd.git
synced 2025-01-09 01:18:19 +03:00
core: optionally send SIGHUP in addition to the configured kill signal
This is useful to fake session ends for processes like shells.
This commit is contained in:
parent
5a4555ba6b
commit
82659fd757
@ -115,16 +115,21 @@
|
||||
<option>control-group</option>.</para>
|
||||
|
||||
<para>Processes will first be
|
||||
terminated via <constant>SIGTERM</constant> (unless the
|
||||
signal to send is changed via
|
||||
<varname>KillSignal=</varname>). If
|
||||
terminated via
|
||||
<constant>SIGTERM</constant> (unless
|
||||
the signal to send is changed via
|
||||
<varname>KillSignal=</varname>). Optionally,
|
||||
this is immediately followed by a
|
||||
<constant>SIGHUP</constant> (if
|
||||
enabled with
|
||||
<varname>SendSIGHUP=</varname>). If
|
||||
then after a delay (configured via the
|
||||
<varname>TimeoutSec=</varname> option)
|
||||
<varname>TimeoutStopSec=</varname> option)
|
||||
processes still remain, the
|
||||
termination request is repeated with
|
||||
the <constant>SIGKILL</constant> signal (unless this is
|
||||
disabled via the
|
||||
<varname>SendSIGKILL=</varname>
|
||||
the <constant>SIGKILL</constant>
|
||||
signal (unless this is disabled via
|
||||
the <varname>SendSIGKILL=</varname>
|
||||
option). See
|
||||
<citerefentry><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
for more
|
||||
@ -139,6 +144,20 @@
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SendSIGHUP=</varname></term>
|
||||
<listitem><para>Specifies whether to
|
||||
send <constant>SIGHUP</constant> to
|
||||
remaining processes immediately after
|
||||
sending the signal configured with
|
||||
<varname>KillSignal=</varname>. This
|
||||
is useful to indicate to shells and
|
||||
shell-like programs that their
|
||||
connection has been severed. Takes a
|
||||
boolean value. Defaults to "no".
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SendSIGKILL=</varname></term>
|
||||
<listitem><para>Specifies whether to
|
||||
@ -149,6 +168,7 @@
|
||||
value. Defaults to "yes".
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -31,5 +31,6 @@ const BusProperty bus_kill_context_properties[] = {
|
||||
{ "KillMode", bus_kill_append_mode, "s", offsetof(KillContext, kill_mode) },
|
||||
{ "KillSignal", bus_property_append_int, "i", offsetof(KillContext, kill_signal) },
|
||||
{ "SendSIGKILL", bus_property_append_bool, "b", offsetof(KillContext, send_sigkill) },
|
||||
{ "SendSIGHUP", bus_property_append_bool, "b", offsetof(KillContext, send_sighup) },
|
||||
{ NULL, }
|
||||
};
|
||||
|
@ -29,10 +29,8 @@
|
||||
#define BUS_KILL_CONTEXT_INTERFACE \
|
||||
" <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n" \
|
||||
" <property name=\"SendSIGKILL\" type=\"b\" access=\"read\"/>\n"
|
||||
|
||||
#define BUS_KILL_COMMAND_INTERFACE(name) \
|
||||
" <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
|
||||
" <property name=\"SendSIGKILL\" type=\"b\" access=\"read\"/>\n" \
|
||||
" <property name=\"SendSIGHUP\" type=\"b\" access=\"read\"/>\n"
|
||||
|
||||
extern const BusProperty bus_kill_context_properties[];
|
||||
|
||||
|
@ -29,6 +29,7 @@ void kill_context_init(KillContext *c) {
|
||||
|
||||
c->kill_signal = SIGTERM;
|
||||
c->send_sigkill = true;
|
||||
c->send_sighup = false;
|
||||
}
|
||||
|
||||
void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
|
||||
@ -40,10 +41,12 @@ void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
|
||||
fprintf(f,
|
||||
"%sKillMode: %s\n"
|
||||
"%sKillSignal: SIG%s\n"
|
||||
"%sSendSIGKILL: %s\n",
|
||||
"%sSendSIGKILL: %s\n"
|
||||
"%sSendSIGHUP: %s\n",
|
||||
prefix, kill_mode_to_string(c->kill_mode),
|
||||
prefix, signal_to_string(c->kill_signal),
|
||||
prefix, yes_no(c->send_sigkill));
|
||||
prefix, yes_no(c->send_sigkill),
|
||||
prefix, yes_no(c->send_sighup));
|
||||
}
|
||||
|
||||
static const char* const kill_mode_table[_KILL_MODE_MAX] = {
|
||||
|
@ -41,6 +41,7 @@ struct KillContext {
|
||||
KillMode kill_mode;
|
||||
int kill_signal;
|
||||
bool send_sigkill;
|
||||
bool send_sighup;
|
||||
};
|
||||
|
||||
typedef enum KillWho {
|
||||
|
@ -79,6 +79,7 @@ $1.UtmpIdentifier, config_parse_unit_string_printf, 0,
|
||||
)m4_dnl
|
||||
m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
|
||||
`$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill)
|
||||
$1.SendSIGHUP, config_parse_bool, 0, offsetof($1, kill_context.send_sighup)
|
||||
$1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode)
|
||||
$1.KillSignal, config_parse_kill_signal, 0, offsetof($1, kill_context.kill_signal)'
|
||||
)m4_dnl
|
||||
|
@ -2542,6 +2542,34 @@ int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) {
|
||||
return UNIT_VTABLE(u)->kill(u, w, signo, error);
|
||||
}
|
||||
|
||||
static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) {
|
||||
Set *pid_set;
|
||||
int r;
|
||||
|
||||
pid_set = set_new(trivial_hash_func, trivial_compare_func);
|
||||
if (!pid_set)
|
||||
return NULL;
|
||||
|
||||
/* Exclude the main/control pids from being killed via the cgroup */
|
||||
if (main_pid > 0) {
|
||||
r = set_put(pid_set, LONG_TO_PTR(main_pid));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (control_pid > 0) {
|
||||
r = set_put(pid_set, LONG_TO_PTR(control_pid));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return pid_set;
|
||||
|
||||
fail:
|
||||
set_free(pid_set);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int unit_kill_common(
|
||||
Unit *u,
|
||||
KillWho who,
|
||||
@ -2582,23 +2610,11 @@ int unit_kill_common(
|
||||
_cleanup_set_free_ Set *pid_set = NULL;
|
||||
int q;
|
||||
|
||||
pid_set = set_new(trivial_hash_func, trivial_compare_func);
|
||||
/* Exclude the main/control pids from being killed via the cgroup */
|
||||
pid_set = unit_pid_set(main_pid, control_pid);
|
||||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Exclude the control/main pid from being killed via the cgroup */
|
||||
if (control_pid > 0) {
|
||||
q = set_put(pid_set, LONG_TO_PTR(control_pid));
|
||||
if (q < 0)
|
||||
return q;
|
||||
}
|
||||
|
||||
if (main_pid > 0) {
|
||||
q = set_put(pid_set, LONG_TO_PTR(main_pid));
|
||||
if (q < 0)
|
||||
return q;
|
||||
}
|
||||
|
||||
q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
|
||||
if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
|
||||
r = q;
|
||||
@ -2949,8 +2965,12 @@ int unit_kill_context(
|
||||
|
||||
log_warning_unit(u->id, "Failed to kill main process %li (%s): %s",
|
||||
(long) main_pid, strna(comm), strerror(-r));
|
||||
} else
|
||||
} else {
|
||||
wait_for_exit = !main_pid_alien;
|
||||
|
||||
if (c->send_sighup)
|
||||
kill(main_pid, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
if (control_pid > 0) {
|
||||
@ -2963,36 +2983,38 @@ int unit_kill_context(
|
||||
log_warning_unit(u->id,
|
||||
"Failed to kill control process %li (%s): %s",
|
||||
(long) control_pid, strna(comm), strerror(-r));
|
||||
} else
|
||||
} else {
|
||||
wait_for_exit = true;
|
||||
|
||||
if (c->send_sighup)
|
||||
kill(control_pid, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
if (c->kill_mode == KILL_CONTROL_GROUP && u->cgroup_path) {
|
||||
_cleanup_set_free_ Set *pid_set = NULL;
|
||||
|
||||
pid_set = set_new(trivial_hash_func, trivial_compare_func);
|
||||
/* Exclude the main/control pids from being killed via the cgroup */
|
||||
pid_set = unit_pid_set(main_pid, control_pid);
|
||||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Exclude the main/control pids from being killed via the cgroup */
|
||||
if (main_pid > 0) {
|
||||
r = set_put(pid_set, LONG_TO_PTR(main_pid));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (control_pid > 0) {
|
||||
r = set_put(pid_set, LONG_TO_PTR(control_pid));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, true, false, pid_set);
|
||||
if (r < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning_unit(u->id, "Failed to kill control group: %s", strerror(-r));
|
||||
} else if (r > 0)
|
||||
} else if (r > 0) {
|
||||
wait_for_exit = true;
|
||||
if (c->send_sighup) {
|
||||
set_free(pid_set);
|
||||
|
||||
pid_set = unit_pid_set(main_pid, control_pid);
|
||||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, SIGHUP, true, true, false, pid_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wait_for_exit;
|
||||
|
@ -25,10 +25,7 @@ TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
|
||||
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
|
||||
# terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
SendSIGHUP=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=getty.target
|
||||
|
@ -25,10 +25,7 @@ StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
|
||||
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
|
||||
# terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
SendSIGHUP=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=getty.target
|
||||
|
@ -25,7 +25,4 @@ StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
|
||||
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
|
||||
# terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
SendSIGHUP=yes
|
||||
|
@ -38,14 +38,11 @@ TTYVHangup=yes
|
||||
TTYVTDisallocate=yes
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
SendSIGHUP=yes
|
||||
|
||||
# Unset locale for the console getty since the console has problems
|
||||
# displaying some internationalized messages.
|
||||
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
|
||||
|
||||
# Some login implementations ignore SIGTERM, so we send SIGHUP
|
||||
# instead, to ensure that login terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
|
||||
[Install]
|
||||
WantedBy=getty.target
|
||||
|
@ -25,7 +25,5 @@ StandardInput=tty-force
|
||||
StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
KillMode=process
|
||||
|
||||
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
|
||||
# terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
IgnoreSIGPIPE=no
|
||||
SendSIGHUP=yes
|
||||
|
@ -32,7 +32,4 @@ TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
|
||||
# Some login implementations ignore SIGTERM, so we send SIGHUP
|
||||
# instead, to ensure that login terminates cleanly.
|
||||
KillSignal=SIGHUP
|
||||
SendSIGHUP=yes
|
||||
|
Loading…
Reference in New Issue
Block a user