chiark / gitweb /
core: unify kill code of mount, service, socket, swap units
authorLennart Poettering <lennart@poettering.net>
Sat, 26 Jan 2013 04:53:30 +0000 (05:53 +0100)
committerLennart Poettering <lennart@poettering.net>
Sat, 26 Jan 2013 04:53:30 +0000 (05:53 +0100)
src/core/mount.c
src/core/service.c
src/core/socket.c
src/core/swap.c
src/core/unit.c
src/core/unit.h

index e5f5e42..2aaf78c 100644 (file)
@@ -877,56 +877,23 @@ static void mount_enter_mounted(Mount *m, MountResult f) {
 
 static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
         int r;
-        Set *pid_set = NULL;
-        bool wait_for_exit = false;
 
         assert(m);
 
         if (f != MOUNT_SUCCESS)
                 m->result = f;
 
-        if (m->kill_context.kill_mode != KILL_NONE) {
-                int sig = (state == MOUNT_MOUNTING_SIGTERM ||
-                           state == MOUNT_UNMOUNTING_SIGTERM ||
-                           state == MOUNT_REMOUNTING_SIGTERM) ? m->kill_context.kill_signal : SIGKILL;
-
-                if (m->control_pid > 0) {
-                        if (kill_and_sigcont(m->control_pid, sig) < 0 && errno != ESRCH)
-
-                                log_warning_unit(UNIT(m)->id,
-                                                 "Failed to kill control process %li: %m",
-                                                 (long) m->control_pid);
-                        else
-                                wait_for_exit = true;
-                }
-
-                if (m->kill_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 (m->control_pid > 0)
-                                if ((r = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0)
-                                        goto fail;
-
-                        r = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, sig, true, false, pid_set, NULL);
-                        if (r < 0) {
-                                if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
-                                        log_warning_unit(UNIT(m)->id,
-                                                         "Failed to kill control group: %s",
-                                                         strerror(-r));
-                        } else if (r > 0)
-                                wait_for_exit = true;
-
-                        set_free(pid_set);
-                        pid_set = NULL;
-                }
-        }
+        r = unit_kill_context(
+                        UNIT(m),
+                        &m->kill_context,
+                        state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM,
+                        -1,
+                        m->control_pid,
+                        false);
+        if (r < 0)
+                goto fail;
 
-        if (wait_for_exit) {
+        if (r > 0) {
                 r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
                 if (r < 0)
                         goto fail;
@@ -947,14 +914,15 @@ fail:
                 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
         else
                 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
-
-        if (pid_set)
-                set_free(pid_set);
 }
 
 void warn_if_dir_nonempty(const char *unit, const char* where) {
+        assert(unit);
+        assert(where);
+
         if (dir_is_empty(where) > 0)
                 return;
+
         log_struct_unit(LOG_NOTICE,
                    unit,
                    "MESSAGE=%s: Directory %s to mount over is not empty, mounting anyway.",
index baddc5a..9141463 100644 (file)
@@ -1955,64 +1955,23 @@ fail:
 
 static void service_enter_signal(Service *s, ServiceState state, ServiceResult f) {
         int r;
-        Set *pid_set = NULL;
-        bool wait_for_exit = false;
 
         assert(s);
 
         if (f != SERVICE_SUCCESS)
                 s->result = f;
 
-        if (s->kill_context.kill_mode != KILL_NONE) {
-                int sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? s->kill_context.kill_signal : SIGKILL;
-
-                if (s->main_pid > 0) {
-                        if (kill_and_sigcont(s->main_pid, sig) < 0 && errno != ESRCH)
-                                log_warning_unit(UNIT(s)->id,
-                                                 "Failed to kill main process %li: %m", (long) s->main_pid);
-                        else
-                                wait_for_exit = !s->main_pid_alien;
-                }
-
-                if (s->control_pid > 0) {
-                        if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
-                                log_warning_unit(UNIT(s)->id,
-                                                 "Failed to kill control process %li: %m", (long) s->control_pid);
-                        else
-                                wait_for_exit = true;
-                }
-
-                if (s->kill_context.kill_mode == KILL_CONTROL_GROUP) {
-
-                        pid_set = set_new(trivial_hash_func, trivial_compare_func);
-                        if (!pid_set) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
-
-                        /* Exclude the main/control pids from being killed via the cgroup */
-                        if (s->main_pid > 0)
-                                if ((r = set_put(pid_set, LONG_TO_PTR(s->main_pid))) < 0)
-                                        goto fail;
-
-                        if (s->control_pid > 0)
-                                if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
-                                        goto fail;
-
-                        r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
-                        if (r < 0) {
-                                if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
-                                        log_warning_unit(UNIT(s)->id,
-                                                         "Failed to kill control group: %s", strerror(-r));
-                        } else if (r > 0)
-                                wait_for_exit = true;
-
-                        set_free(pid_set);
-                        pid_set = NULL;
-                }
-        }
+        r = unit_kill_context(
+                        UNIT(s),
+                        &s->kill_context,
+                        state != SERVICE_STOP_SIGTERM && state != SERVICE_FINAL_SIGTERM,
+                        s->main_pid,
+                        s->control_pid,
+                        s->main_pid_alien);
+        if (r < 0)
+                goto fail;
 
-        if (wait_for_exit) {
+        if (r > 0) {
                 if (s->timeout_stop_usec > 0) {
                         r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
                         if (r < 0)
@@ -2035,9 +1994,6 @@ fail:
                 service_enter_stop_post(s, SERVICE_FAILURE_RESOURCES);
         else
                 service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
-
-        if (pid_set)
-                set_free(pid_set);
 }
 
 static void service_enter_stop(Service *s, ServiceResult f) {
index f74d88e..2105369 100644 (file)
@@ -1288,54 +1288,23 @@ fail:
 
 static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
         int r;
-        Set *pid_set = NULL;
-        bool wait_for_exit = false;
 
         assert(s);
 
         if (f != SOCKET_SUCCESS)
                 s->result = f;
 
-        if (s->kill_context.kill_mode != KILL_NONE) {
-                int sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_FINAL_SIGTERM) ? s->kill_context.kill_signal : SIGKILL;
-
-                if (s->control_pid > 0) {
-                        if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
-
-                                log_warning_unit(UNIT(s)->id,
-                                                 "Failed to kill control process %li: %m",
-                                                 (long) s->control_pid);
-                        else
-                                wait_for_exit = true;
-                }
-
-                if (s->kill_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;
-
-                        r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
-                        if (r < 0) {
-                                if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
-                                        log_warning_unit(UNIT(s)->id,
-                                                         "Failed to kill control group: %s",
-                                                         strerror(-r));
-                        } else if (r > 0)
-                                wait_for_exit = true;
-
-                        set_free(pid_set);
-                        pid_set = NULL;
-                }
-        }
+        r = unit_kill_context(
+                        UNIT(s),
+                        &s->kill_context,
+                        state != SOCKET_STOP_PRE_SIGTERM && state != SOCKET_FINAL_SIGTERM,
+                        -1,
+                        s->control_pid,
+                        false);
+        if (r < 0)
+                goto fail;
 
-        if (wait_for_exit) {
+        if (r > 0) {
                 r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
                 if (r < 0)
                         goto fail;
@@ -1357,9 +1326,6 @@ fail:
                 socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES);
         else
                 socket_enter_dead(s, SOCKET_FAILURE_RESOURCES);
-
-        if (pid_set)
-                set_free(pid_set);
 }
 
 static void socket_enter_stop_pre(Socket *s, SocketResult f) {
index a2f1187..61ce831 100644 (file)
@@ -646,57 +646,23 @@ static void swap_enter_active(Swap *s, SwapResult f) {
 
 static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
         int r;
-        Set *pid_set = NULL;
-        bool wait_for_exit = false;
 
         assert(s);
 
         if (f != SWAP_SUCCESS)
                 s->result = f;
 
-        if (s->kill_context.kill_mode != KILL_NONE) {
-                int sig = (state == SWAP_ACTIVATING_SIGTERM ||
-                           state == SWAP_DEACTIVATING_SIGTERM) ? s->kill_context.kill_signal : SIGKILL;
-
-                if (s->control_pid > 0) {
-                        if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
-
-                                log_warning_unit(UNIT(s)->id,
-                                                 "Failed to kill control process %li: %m",
-                                                 (long) s->control_pid);
-                        else
-                                wait_for_exit = true;
-                }
-
-                if (s->kill_context.kill_mode == KILL_CONTROL_GROUP) {
-
-                        pid_set = set_new(trivial_hash_func, trivial_compare_func);
-                        if (!pid_set) {
-                                r = log_oom();
-                                goto fail;
-                        }
-
-                        /* Exclude the control pid from being killed via the cgroup */
-                        if (s->control_pid > 0) {
-                                r = set_put(pid_set, LONG_TO_PTR(s->control_pid));
-                                if (r < 0)
-                                        goto fail;
-                        }
-
-                        r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
-                        if (r < 0) {
-                                if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
-                                        log_warning_unit(UNIT(s)->id,
-                                                         "Failed to kill control group: %s", strerror(-r));
-                        } else if (r > 0)
-                                wait_for_exit = true;
-
-                        set_free(pid_set);
-                        pid_set = NULL;
-                }
-        }
+        r = unit_kill_context(
+                        UNIT(s),
+                        &s->kill_context,
+                        state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM,
+                        -1,
+                        s->control_pid,
+                        false);
+        if (r < 0)
+                goto fail;
 
-        if (wait_for_exit) {
+        if (r > 0) {
                 r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
                 if (r < 0)
                         goto fail;
@@ -712,9 +678,6 @@ fail:
                          "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
 
         swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
-
-        if (pid_set)
-                set_free(pid_set);
 }
 
 static void swap_enter_activating(Swap *s) {
index b2a4765..f7d00b6 100644 (file)
@@ -2807,6 +2807,82 @@ int unit_remove_drop_in(Unit *u, bool runtime, const char *name) {
         return 0;
 }
 
+int unit_kill_context(
+                Unit *u,
+                KillContext *c,
+                bool sigkill,
+                pid_t main_pid,
+                pid_t control_pid,
+                bool main_pid_alien) {
+
+        int sig, wait_for_exit = 0, r;
+
+        assert(u);
+        assert(c);
+
+        if (c->kill_mode == KILL_NONE)
+                return 0;
+
+        sig = sigkill ? SIGKILL : c->kill_signal;
+
+        if (main_pid > 0) {
+                r = kill_and_sigcont(main_pid, sig);
+
+                if (r < 0 && r != -ESRCH) {
+                        _cleanup_free_ char *comm = NULL;
+                        get_process_comm(main_pid, &comm);
+
+                        log_warning_unit(u->id, "Failed to kill main process %li (%s): %s",
+                                         (long) main_pid, strna(comm), strerror(-r));
+                } else
+                        wait_for_exit = !main_pid_alien;
+        }
+
+        if (control_pid > 0) {
+                r = kill_and_sigcont(control_pid, sig);
+
+                if (r < 0 && r != -ESRCH) {
+                        _cleanup_free_ char *comm = NULL;
+                        get_process_comm(control_pid, &comm);
+
+                        log_warning_unit(u->id,
+                                         "Failed to kill control process %li (%s): %s",
+                                         (long) control_pid, strna(comm), strerror(-r));
+                } else
+                        wait_for_exit = true;
+        }
+
+        if (c->kill_mode == KILL_CONTROL_GROUP) {
+                _cleanup_set_free_ Set *pid_set = NULL;
+
+                pid_set = set_new(trivial_hash_func, trivial_compare_func);
+                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 = cgroup_bonding_kill_list(u->cgroup_bondings, sig, true, false, pid_set, NULL);
+                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)
+                        wait_for_exit = true;
+        }
+
+        return wait_for_exit;
+}
+
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
         [UNIT_ACTIVE] = "active",
         [UNIT_RELOADING] = "reloading",
index 297b35d..c902103 100644 (file)
@@ -557,6 +557,8 @@ ExecContext *unit_get_exec_context(Unit *u);
 int unit_write_drop_in(Unit *u, bool runtime, const char *name, const char *data);
 int unit_remove_drop_in(Unit *u, bool runtime, const char *name);
 
+int unit_kill_context(Unit *u, KillContext *c, bool sigkill, pid_t main_pid, pid_t control_pid, bool main_pid_alien);
+
 const char *unit_active_state_to_string(UnitActiveState i);
 UnitActiveState unit_active_state_from_string(const char *s);