mirror of
https://github.com/systemd/systemd
synced 2024-11-05 18:25:39 +00:00
kill: always send SIGCONT after SIGTERM
When we kill a process to terminate it make sure to send SIGCONT to ensure it is unpaused and processes the signal.
This commit is contained in:
parent
2b590e135f
commit
430c18ed7f
14 changed files with 66 additions and 46 deletions
6
TODO
6
TODO
|
@ -20,13 +20,11 @@ F15:
|
|||
|
||||
* hook emergency.target into local-fs.target in some way as OnFailure with isolate
|
||||
|
||||
* convince Karel to give us our own mount option prefix
|
||||
|
||||
Features:
|
||||
|
||||
* show failure error string in "systemctl status"
|
||||
* introduce "x-systemd-automount" as alternative to the "comment=systemd.automount" mount option
|
||||
|
||||
* send SIGCONT before SIGTERM
|
||||
* show failure error string in "systemctl status"
|
||||
|
||||
* make sure timeouts are applied to Type=oneshot services.
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ int cg_rmdir(const char *controller, const char *path) {
|
|||
return r < 0 ? -errno : 0;
|
||||
}
|
||||
|
||||
int cg_kill(const char *controller, const char *path, int sig, bool ignore_self, Set *s) {
|
||||
int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
|
||||
bool done = false;
|
||||
int r, ret = 0;
|
||||
pid_t my_pid;
|
||||
|
@ -211,8 +211,13 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self,
|
|||
if (kill(pid, sig) < 0) {
|
||||
if (ret >= 0 && errno != ESRCH)
|
||||
ret = -errno;
|
||||
} else if (ret == 0)
|
||||
} else if (ret == 0) {
|
||||
|
||||
if (sigcont)
|
||||
kill(pid, SIGCONT);
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
done = false;
|
||||
|
||||
|
@ -250,7 +255,7 @@ finish:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self, bool rem, Set *s) {
|
||||
int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
|
||||
int r, ret = 0;
|
||||
DIR *d = NULL;
|
||||
char *fn;
|
||||
|
@ -264,7 +269,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool ig
|
|||
if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
|
||||
return -ENOMEM;
|
||||
|
||||
ret = cg_kill(controller, path, sig, ignore_self, s);
|
||||
ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
|
||||
|
||||
if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) {
|
||||
if (ret >= 0 && r != -ENOENT)
|
||||
|
@ -286,7 +291,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool ig
|
|||
goto finish;
|
||||
}
|
||||
|
||||
r = cg_kill_recursive(controller, p, sig, ignore_self, rem, s);
|
||||
r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
|
||||
free(p);
|
||||
|
||||
if (r != 0 && ret >= 0)
|
||||
|
@ -336,7 +341,7 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path, bool re
|
|||
else
|
||||
sig = 0;
|
||||
|
||||
if ((r = cg_kill_recursive(controller, path, sig, true, rem, NULL)) <= 0)
|
||||
if ((r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL)) <= 0)
|
||||
return r;
|
||||
|
||||
usleep(200 * USEC_PER_MSEC);
|
||||
|
|
|
@ -37,8 +37,8 @@ int cg_read_pid(FILE *f, pid_t *_pid);
|
|||
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
|
||||
int cg_read_subgroup(DIR *d, char **fn);
|
||||
|
||||
int cg_kill(const char *controller, const char *path, int sig, bool ignore_self, Set *s);
|
||||
int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self, bool remove, Set *s);
|
||||
int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s);
|
||||
int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool remove, Set *s);
|
||||
int cg_kill_recursive_and_wait(const char *controller, const char *path, bool remove);
|
||||
|
||||
int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self);
|
||||
|
|
|
@ -140,7 +140,7 @@ int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cgroup_bonding_kill(CGroupBonding *b, int sig, Set *s) {
|
||||
int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s) {
|
||||
assert(b);
|
||||
assert(sig >= 0);
|
||||
|
||||
|
@ -148,10 +148,10 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig, Set *s) {
|
|||
if (!b->realized || !b->ours)
|
||||
return 0;
|
||||
|
||||
return cg_kill_recursive(b->controller, b->path, sig, true, false, s);
|
||||
return cg_kill_recursive(b->controller, b->path, sig, sigcont, true, false, s);
|
||||
}
|
||||
|
||||
int cgroup_bonding_kill_list(CGroupBonding *first, int sig, Set *s) {
|
||||
int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s) {
|
||||
CGroupBonding *b;
|
||||
Set *allocated_set = NULL;
|
||||
int ret = -EAGAIN, r;
|
||||
|
@ -161,7 +161,7 @@ int cgroup_bonding_kill_list(CGroupBonding *first, int sig, Set *s) {
|
|||
return -ENOMEM;
|
||||
|
||||
LIST_FOREACH(by_unit, b, first) {
|
||||
if ((r = cgroup_bonding_kill(b, sig, s)) < 0) {
|
||||
if ((r = cgroup_bonding_kill(b, sig, sigcont, s)) < 0) {
|
||||
if (r == -EAGAIN || r == -ESRCH)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -59,8 +59,8 @@ void cgroup_bonding_free_list(CGroupBonding *first);
|
|||
int cgroup_bonding_install(CGroupBonding *b, pid_t pid);
|
||||
int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid);
|
||||
|
||||
int cgroup_bonding_kill(CGroupBonding *b, int sig, Set *s);
|
||||
int cgroup_bonding_kill_list(CGroupBonding *first, int sig, Set *s);
|
||||
int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s);
|
||||
int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s);
|
||||
|
||||
void cgroup_bonding_trim(CGroupBonding *first, bool delete_root);
|
||||
void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root);
|
||||
|
|
|
@ -894,8 +894,10 @@ fail:
|
|||
|
||||
closelog();
|
||||
|
||||
if (pam_pid > 1)
|
||||
if (pam_pid > 1) {
|
||||
kill(pam_pid, SIGTERM);
|
||||
kill(pam_pid, SIGCONT);
|
||||
}
|
||||
|
||||
return EXIT_PAM;
|
||||
}
|
||||
|
|
10
src/mount.c
10
src/mount.c
|
@ -729,9 +729,9 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) {
|
|||
state == MOUNT_REMOUNTING_SIGTERM) ? m->exec_context.kill_signal : SIGKILL;
|
||||
|
||||
if (m->control_pid > 0) {
|
||||
if (kill(m->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-m->control_pid :
|
||||
m->control_pid, sig) < 0 && errno != ESRCH)
|
||||
if (kill_and_sigcont(m->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-m->control_pid :
|
||||
m->control_pid, sig) < 0 && errno != ESRCH)
|
||||
|
||||
log_warning("Failed to kill control process %li: %m", (long) m->control_pid);
|
||||
else
|
||||
|
@ -750,7 +750,7 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) {
|
|||
if ((r = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0)
|
||||
goto fail;
|
||||
|
||||
if ((r = cgroup_bonding_kill_list(m->meta.cgroup_bondings, sig, pid_set)) < 0) {
|
||||
if ((r = cgroup_bonding_kill_list(m->meta.cgroup_bondings, sig, true, pid_set)) < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning("Failed to kill control group: %s", strerror(-r));
|
||||
} else if (r > 0)
|
||||
|
@ -1678,7 +1678,7 @@ static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if ((q = cgroup_bonding_kill_list(m->meta.cgroup_bondings, signo, pid_set)) < 0)
|
||||
if ((q = cgroup_bonding_kill_list(m->meta.cgroup_bondings, signo, false, pid_set)) < 0)
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
r = q;
|
||||
}
|
||||
|
|
|
@ -1830,9 +1830,9 @@ static void service_enter_signal(Service *s, ServiceState state, bool success) {
|
|||
int sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? s->exec_context.kill_signal : SIGKILL;
|
||||
|
||||
if (s->main_pid > 0) {
|
||||
if (kill(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-s->main_pid :
|
||||
s->main_pid, sig) < 0 && errno != ESRCH)
|
||||
if (kill_and_sigcont(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-s->main_pid :
|
||||
s->main_pid, sig) < 0 && errno != ESRCH)
|
||||
|
||||
log_warning("Failed to kill main process %li: %m", (long) s->main_pid);
|
||||
else
|
||||
|
@ -1840,9 +1840,9 @@ static void service_enter_signal(Service *s, ServiceState state, bool success) {
|
|||
}
|
||||
|
||||
if (s->control_pid > 0) {
|
||||
if (kill(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-s->control_pid :
|
||||
s->control_pid, sig) < 0 && errno != ESRCH)
|
||||
if (kill_and_sigcont(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-s->control_pid :
|
||||
s->control_pid, sig) < 0 && errno != ESRCH)
|
||||
|
||||
log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
|
||||
else
|
||||
|
@ -1865,7 +1865,7 @@ static void service_enter_signal(Service *s, ServiceState state, bool success) {
|
|||
if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
|
||||
goto fail;
|
||||
|
||||
if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, pid_set)) < 0) {
|
||||
if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, true, pid_set)) < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning("Failed to kill control group: %s", strerror(-r));
|
||||
} else if (r > 0)
|
||||
|
@ -3230,7 +3230,7 @@ static int service_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusErro
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, pid_set)) < 0)
|
||||
if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, false, pid_set)) < 0)
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
r = q;
|
||||
}
|
||||
|
|
10
src/socket.c
10
src/socket.c
|
@ -1039,9 +1039,9 @@ static void socket_enter_signal(Socket *s, SocketState state, bool success) {
|
|||
int sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_FINAL_SIGTERM) ? s->exec_context.kill_signal : SIGKILL;
|
||||
|
||||
if (s->control_pid > 0) {
|
||||
if (kill(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-s->control_pid :
|
||||
s->control_pid, sig) < 0 && errno != ESRCH)
|
||||
if (kill_and_sigcont(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-s->control_pid :
|
||||
s->control_pid, sig) < 0 && errno != ESRCH)
|
||||
|
||||
log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
|
||||
else
|
||||
|
@ -1060,7 +1060,7 @@ static void socket_enter_signal(Socket *s, SocketState state, bool success) {
|
|||
if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
|
||||
goto fail;
|
||||
|
||||
if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, pid_set)) < 0) {
|
||||
if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, true, pid_set)) < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning("Failed to kill control group: %s", strerror(-r));
|
||||
} else if (r > 0)
|
||||
|
@ -1852,7 +1852,7 @@ static int socket_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, pid_set)) < 0)
|
||||
if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, false, pid_set)) < 0)
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
r = q;
|
||||
}
|
||||
|
|
10
src/swap.c
10
src/swap.c
|
@ -660,9 +660,9 @@ static void swap_enter_signal(Swap *s, SwapState state, bool success) {
|
|||
state == SWAP_DEACTIVATING_SIGTERM) ? s->exec_context.kill_signal : SIGKILL;
|
||||
|
||||
if (s->control_pid > 0) {
|
||||
if (kill(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-s->control_pid :
|
||||
s->control_pid, sig) < 0 && errno != ESRCH)
|
||||
if (kill_and_sigcont(s->exec_context.kill_mode == KILL_PROCESS_GROUP ?
|
||||
-s->control_pid :
|
||||
s->control_pid, sig) < 0 && errno != ESRCH)
|
||||
|
||||
log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
|
||||
else
|
||||
|
@ -681,7 +681,7 @@ static void swap_enter_signal(Swap *s, SwapState state, bool success) {
|
|||
if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
|
||||
goto fail;
|
||||
|
||||
if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, pid_set)) < 0) {
|
||||
if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, true, pid_set)) < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning("Failed to kill control group: %s", strerror(-r));
|
||||
} else if (r > 0)
|
||||
|
@ -1301,7 +1301,7 @@ static int swap_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, pid_set)) < 0)
|
||||
if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, false, pid_set)) < 0)
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
r = q;
|
||||
}
|
||||
|
|
|
@ -5532,6 +5532,7 @@ static void pager_close(void) {
|
|||
|
||||
/* Inform pager that we are done */
|
||||
fclose(stdout);
|
||||
kill(pager_pid, SIGCONT);
|
||||
wait_for_terminate(pager_pid, &dummy);
|
||||
pager_pid = 0;
|
||||
}
|
||||
|
@ -5544,6 +5545,7 @@ static void agent_close(void) {
|
|||
|
||||
/* Inform agent that we are done */
|
||||
kill(agent_pid, SIGTERM);
|
||||
kill(agent_pid, SIGCONT);
|
||||
wait_for_terminate(agent_pid, &dummy);
|
||||
agent_pid = 0;
|
||||
}
|
||||
|
|
|
@ -61,16 +61,16 @@ int main(int argc, char*argv[]) {
|
|||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) == 0);
|
||||
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, NULL) == 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, NULL) > 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) == 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) > 0);
|
||||
|
||||
assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", "/test-a", false, false) > 0);
|
||||
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) == 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);
|
||||
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, NULL) > 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, NULL) == 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) > 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) == 0);
|
||||
|
||||
cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false);
|
||||
|
||||
|
|
11
src/util.c
11
src/util.c
|
@ -3977,6 +3977,17 @@ finish:
|
|||
hashmap_free_free(pids);
|
||||
}
|
||||
|
||||
int kill_and_sigcont(pid_t pid, int sig) {
|
||||
int r;
|
||||
|
||||
r = kill(pid, sig) < 0 ? -errno : 0;
|
||||
|
||||
if (r >= 0)
|
||||
kill(pid, SIGCONT);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const char *const ioprio_class_table[] = {
|
||||
[IOPRIO_CLASS_NONE] = "none",
|
||||
[IOPRIO_CLASS_RT] = "realtime",
|
||||
|
|
|
@ -383,6 +383,8 @@ int detect_virtualization(const char **id);
|
|||
|
||||
void execute_directory(const char *directory, DIR *_d, char *argv[]);
|
||||
|
||||
int kill_and_sigcont(pid_t pid, int sig);
|
||||
|
||||
#define NULSTR_FOREACH(i, l) \
|
||||
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
|
||||
|
||||
|
|
Loading…
Reference in a new issue