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:
Lennart Poettering
2013-07-30 01:54:59 +02:00
parent 5a4555ba6b
commit 82659fd757
13 changed files with 97 additions and 68 deletions
+1
View File
@@ -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, }
};
+2 -4
View File
@@ -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[];
+5 -2
View File
@@ -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] = {
+1
View File
@@ -41,6 +41,7 @@ struct KillContext {
KillMode kill_mode;
int kill_signal;
bool send_sigkill;
bool send_sighup;
};
typedef enum KillWho {
+1
View File
@@ -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
+53 -31
View File
@@ -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;