]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
killall: port killing spree loop over to PidRef
authorLennart Poettering <lennart@poettering.net>
Tue, 17 Oct 2023 11:43:29 +0000 (13:43 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 18 Oct 2023 12:49:40 +0000 (14:49 +0200)
src/basic/cgroup-util.c
src/shared/killall.c

index f38262ca11530e558fd45cbf33e952c1502c7d00..5caf85f443865cf99b23a1b19ecaeacc8faac75a 100644 (file)
@@ -311,7 +311,6 @@ static int cg_kill_items(
 
         do {
                 _cleanup_fclose_ FILE *f = NULL;
-                pid_t pid = 0;
                 done = true;
 
                 r = cg_enumerate_items(SYSTEMD_CGROUP_CONTROLLER, path, &f, item);
@@ -359,7 +358,7 @@ static int cg_kill_items(
 
                         done = false;
 
-                        r = set_put(s, PID_TO_PTR(pid));
+                        r = set_put(s, PID_TO_PTR(pidref.pid));
                         if (r < 0) {
                                 if (ret >= 0)
                                         return r;
index df0f450a880f3801759d17d31e549f6ca93cdf82..9c2babe7d28cd4cdc165b68e00f65682ddce55f9 100644 (file)
@@ -46,13 +46,15 @@ static bool argv_has_at(pid_t pid) {
         return c == '@';
 }
 
-static bool is_survivor_cgroup(pid_t pid) {
+static bool is_survivor_cgroup(const PidRef *pid) {
         _cleanup_free_ char *cgroup_path = NULL;
         int r;
 
-        r = cg_pid_get_path(/* root= */ NULL, pid, &cgroup_path);
+        assert(pidref_is_set(pid));
+
+        r = cg_pidref_get_path(/* root= */ NULL, pid, &cgroup_path);
         if (r < 0) {
-                log_warning_errno(r, "Failed to get cgroup path of process " PID_FMT ", ignoring: %m", pid);
+                log_warning_errno(r, "Failed to get cgroup path of process " PID_FMT ", ignoring: %m", pid->pid);
                 return false;
         }
 
@@ -68,16 +70,18 @@ static bool is_survivor_cgroup(pid_t pid) {
         return r > 0;
 }
 
-static bool ignore_proc(pid_t pid, bool warn_rootfs) {
+static bool ignore_proc(const PidRef *pid, bool warn_rootfs) {
         uid_t uid;
         int r;
 
+        assert(pidref_is_set(pid));
+
         /* We are PID 1, let's not commit suicide */
-        if (pid <= 1)
+        if (pid->pid == 1)
                 return true;
 
         /* Ignore kernel threads */
-        r = pid_is_kernel_thread(pid);
+        r = pidref_is_kernel_thread(pid);
         if (r != 0)
                 return true; /* also ignore processes where we can't determine this */
 
@@ -85,7 +89,7 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) {
         if (is_survivor_cgroup(pid))
                 return true;
 
-        r = pid_get_uid(pid, &uid);
+        r = pidref_get_uid(pid, &uid);
         if (r < 0)
                 return true; /* not really, but better safe than sorry */
 
@@ -93,20 +97,20 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) {
         if (uid != 0)
                 return false;
 
-        if (!argv_has_at(pid))
+        if (!argv_has_at(pid->pid))
                 return false;
 
         if (warn_rootfs &&
-            pid_from_same_root_fs(pid) == 0) {
+            pid_from_same_root_fs(pid->pid) == 0) {
 
                 _cleanup_free_ char *comm = NULL;
 
-                (void) pid_get_comm(pid, &comm);
+                (void) pidref_get_comm(pid, &comm);
 
                 log_notice("Process " PID_FMT " (%s) has been marked to be excluded from killing. It is "
                            "running from the root file system, and thus likely to block re-mounting of the "
                            "root file system to read-only. Please consider moving it into an initrd file "
-                           "system instead.", pid, strna(comm));
+                           "system instead.", pid->pid, strna(comm));
         }
 
         return true;
@@ -125,7 +129,7 @@ static void log_children_no_yet_killed(Set *pids) {
                 else
                         r = strextendf(&lst_child, ", " PID_FMT, PTR_TO_PID(p));
                 if (r < 0)
-                        return (void) log_oom();
+                        return (void) log_oom_warning();
         }
 
         if (isempty(lst_child))
@@ -223,59 +227,57 @@ static int wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
 
 static int killall(int sig, Set *pids, bool send_sighup) {
         _cleanup_closedir_ DIR *dir = NULL;
-        int n_killed = 0;
+        int n_killed = 0, r;
 
         /* Send the specified signal to all remaining processes, if not excluded by ignore_proc().
          * Returns the number of processes to which the specified signal was sent */
 
-        dir = opendir("/proc");
-        if (!dir)
-                return log_warning_errno(errno, "opendir(/proc) failed: %m");
-
-        FOREACH_DIRENT_ALL(de, dir, break) {
-                pid_t pid;
-                int r;
+        r = proc_dir_open(&dir);
+        if (r < 0)
+                return log_warning_errno(r, "opendir(/proc) failed: %m");
 
-                if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN))
-                        continue;
+        for (;;) {
+                _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
 
-                if (parse_pid(de->d_name, &pid) < 0)
-                        continue;
+                r = proc_dir_read_pidref(dir, &pidref);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to enumerate /proc: %m");
+                if (r == 0)
+                        break;
 
-                if (ignore_proc(pid, sig == SIGKILL && !in_initrd()))
+                if (ignore_proc(&pidref, sig == SIGKILL && !in_initrd()))
                         continue;
 
                 if (sig == SIGKILL) {
                         _cleanup_free_ char *s = NULL;
 
-                        (void) pid_get_comm(pid, &s);
-                        log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s));
+                        (void) pidref_get_comm(&pidref, &s);
+                        log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pidref.pid, strna(s));
                 }
 
-                if (kill(pid, sig) >= 0) {
+                r = pidref_kill(&pidref, sig);
+                if (r < 0) {
+                        if (errno != -ESRCH)
+                                log_warning_errno(errno, "Could not kill " PID_FMT ", ignoring: %m", pidref.pid);
+                } else {
                         n_killed++;
                         if (pids) {
-                                r = set_put(pids, PID_TO_PTR(pid));
+                                r = set_put(pids, PID_TO_PTR(pidref.pid));
                                 if (r < 0)
-                                        log_oom();
+                                        (void) log_oom_warning();
                         }
-                } else if (errno != ENOENT)
-                        log_warning_errno(errno, "Could not kill %d: %m", pid);
+                }
 
                 if (send_sighup) {
-                        /* Optionally, also send a SIGHUP signal, but
-                        only if the process has a controlling
-                        tty. This is useful to allow handling of
-                        shells which ignore SIGTERM but react to
-                        SIGHUP. We do not send this to processes that
-                        have no controlling TTY since we don't want to
-                        trigger reloads of daemon processes. Also we
-                        make sure to only send this after SIGTERM so
-                        that SIGTERM is always first in the queue. */
-
-                        if (get_ctty_devnr(pid, NULL) >= 0)
+                        /* Optionally, also send a SIGHUP signal, but only if the process has a controlling
+                         * tty. This is useful to allow handling of shells which ignore SIGTERM but react to
+                         * SIGHUP. We do not send this to processes that have no controlling TTY since we
+                         * don't want to trigger reloads of daemon processes. Also we make sure to only send
+                         * this after SIGTERM so that SIGTERM is always first in the queue. */
+
+                        if (get_ctty_devnr(pidref.pid, NULL) >= 0)
                                 /* it's OK if the process is gone, just ignore the result */
-                                (void) kill(pid, SIGHUP);
+                                (void) pidref_kill(&pidref, SIGHUP);
                 }
         }