summaryrefslogtreecommitdiff
path: root/src/socket.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-08-31 23:24:47 +0200
committerLennart Poettering <lennart@poettering.net>2010-08-31 23:24:47 +0200
commitca949c9dcf17ea8d6512ac4c5c1a806ded9b8dc1 (patch)
treef5c0f995815f9b50ff54602a2a34bdc1ead51405 /src/socket.c
parent22f4096ca96acd504ac74e7dfad96f07edb6da51 (diff)
service: rework killing logic so that we always kill the main process, even if it left our service cgroup
Related to: http://bugzilla.redhat.com/show_bug.cgi?id=626477
Diffstat (limited to 'src/socket.c')
-rw-r--r--src/socket.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/src/socket.c b/src/socket.c
index c4a95579b5..fd975fd99b 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -997,7 +997,8 @@ fail:
static void socket_enter_signal(Socket *s, SocketState state, bool success) {
int r;
- bool sent = false;
+ Set *pid_set = NULL;
+ bool wait_for_exit = false;
assert(s);
@@ -1007,23 +1008,39 @@ static void socket_enter_signal(Socket *s, SocketState state, bool success) {
if (s->exec_context.kill_mode != KILL_NONE) {
int sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_FINAL_SIGTERM) ? s->exec_context.kill_signal : SIGKILL;
- if (s->exec_context.kill_mode == KILL_CONTROL_GROUP) {
+ 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 ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig)) < 0) {
- if (r != -EAGAIN && r != -ESRCH)
- goto fail;
- } else
- sent = true;
+ log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
+ else
+ wait_for_exit = true;
}
- if (!sent && s->control_pid > 0)
- if (kill(s->exec_context.kill_mode == KILL_PROCESS ? s->control_pid : -s->control_pid, sig) < 0 && errno != ESRCH) {
- r = -errno;
+ if (s->exec_context.kill_mode == KILL_CONTROL_GROUP) {
+
+ if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
+ r = -ENOMEM;
goto fail;
}
+
+ /* Exclude the control pid from being killed via the cgroup */
+ if (s->control_pid > 0)
+ 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 != -EAGAIN && r != -ESRCH && r != -ENOENT)
+ log_warning("Failed to kill control group: %s", strerror(-r));
+ } else if (r > 0)
+ wait_for_exit = true;
+
+ set_free(pid_set);
+ }
}
- if (sent && s->control_pid > 0) {
+ if (wait_for_exit) {
if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
goto fail;
@@ -1042,6 +1059,9 @@ fail:
socket_enter_stop_post(s, false);
else
socket_enter_dead(s, false);
+
+ if (pid_set)
+ set_free(pid_set);
}
static void socket_enter_stop_pre(Socket *s, bool success) {