]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/killall.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / core / killall.c
index 77f145b4d1a006057b9415f1f097c2ef26d7d712..e77763e161c6fb09a08e6061f84c68dac79b8182 100644 (file)
@@ -1,5 +1,4 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
 #include <unistd.h>
 
 #include "alloc-util.h"
+#include "def.h"
+#include "dirent-util.h"
 #include "fd-util.h"
-#include "formats-util.h"
+#include "format-util.h"
 #include "killall.h"
 #include "parse-util.h"
 #include "process-util.h"
@@ -35,9 +36,7 @@
 #include "terminal-util.h"
 #include "util.h"
 
-#define TIMEOUT_USEC (10 * USEC_PER_SEC)
-
-static bool ignore_proc(pid_t pid) {
+static bool ignore_proc(pid_t pid, bool warn_rootfs) {
         _cleanup_fclose_ FILE *f = NULL;
         char c;
         const char *p;
@@ -68,14 +67,26 @@ static bool ignore_proc(pid_t pid) {
         if (count <= 0)
                 return true;
 
-        /* Processes with argv[0][0] = '@' we ignore from the killing
-         * spree.
+        /* Processes with argv[0][0] = '@' we ignore from the killing spree.
          *
          * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
-        if (count == 1 && c == '@')
-                return true;
+        if (c != '@')
+                return false;
+
+        if (warn_rootfs &&
+            pid_from_same_root_fs(pid) == 0) {
+
+                _cleanup_free_ char *comm = NULL;
+
+                get_process_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));
+        }
 
-        return false;
+        return true;
 }
 
 static void wait_for_children(Set *pids, sigset_t *mask) {
@@ -86,7 +97,7 @@ static void wait_for_children(Set *pids, sigset_t *mask) {
         if (set_isempty(pids))
                 return;
 
-        until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
+        until = now(CLOCK_MONOTONIC) + DEFAULT_TIMEOUT_USEC;
         for (;;) {
                 struct timespec ts;
                 int k;
@@ -119,9 +130,9 @@ static void wait_for_children(Set *pids, sigset_t *mask) {
                  * might not be our child. */
                 SET_FOREACH(p, pids, i) {
 
-                        /* We misuse getpgid as a check whether a
-                         * process still exists. */
-                        if (getpgid(PTR_TO_PID(p)) >= 0)
+                        /* kill(pid, 0) sends no signal, but it tells
+                         * us whether the process still exists. */
+                        if (kill(PTR_TO_PID(p), 0) == 0)
                                 continue;
 
                         if (errno != ESRCH)
@@ -160,18 +171,17 @@ static int killall(int sig, Set *pids, bool send_sighup) {
         if (!dir)
                 return -errno;
 
-        while ((d = readdir(dir))) {
+        FOREACH_DIRENT_ALL(d, dir, break) {
                 pid_t pid;
                 int r;
 
-                if (d->d_type != DT_DIR &&
-                    d->d_type != DT_UNKNOWN)
+                if (!IN_SET(d->d_type, DT_DIR, DT_UNKNOWN))
                         continue;
 
                 if (parse_pid(d->d_name, &pid) < 0)
                         continue;
 
-                if (ignore_proc(pid))
+                if (ignore_proc(pid, sig == SIGKILL && !in_initrd()))
                         continue;
 
                 if (sig == SIGKILL) {
@@ -203,7 +213,8 @@ static int killall(int sig, Set *pids, bool send_sighup) {
 
 
                         if (get_ctty_devnr(pid, NULL) >= 0)
-                                kill(pid, SIGHUP);
+                                /* it's OK if the process is gone, just ignore the result */
+                                (void) kill(pid, SIGHUP);
                 }
         }