chiark / gitweb /
shutdown: exclude processes with argv[0][0] from killing
[elogind.git] / src / shutdown.c
index 11213f9d595a288c57e3d803d3ed8d21ff16a115..46b5aea1c80d940b385db0ccb9264fbfb6881e93 100644 (file)
 #define FINALIZE_ATTEMPTS 50
 
 static bool ignore_proc(pid_t pid) {
 #define FINALIZE_ATTEMPTS 50
 
 static bool ignore_proc(pid_t pid) {
+        char buf[PATH_MAX];
+        FILE *f;
+        char c;
+        size_t count;
+        uid_t uid;
+        int r;
+
+        /* We are PID 1, let's not commit suicide */
         if (pid == 1)
                 return true;
 
         if (pid == 1)
                 return true;
 
-        /* TODO: add more ignore rules here: device-mapper, etc */
+        r = get_process_uid(pid, &uid);
+        if (r < 0)
+                return true; /* not really, but better safe than sorry */
 
 
-        return false;
-}
+        /* Non-root processes otherwise are always subject to be killed */
+        if (uid != 0)
+                return false;
 
 
-static bool is_kernel_thread(pid_t pid)
-{
-        char buf[PATH_MAX];
-        FILE *f;
-        char c;
-        size_t count;
+        snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long) pid);
+        char_array_0(buf);
 
 
-        snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long)pid);
         f = fopen(buf, "re");
         if (!f)
                 return true; /* not really, but has the desired effect */
 
         count = fread(&c, 1, 1, f);
         fclose(f);
         f = fopen(buf, "re");
         if (!f)
                 return true; /* not really, but has the desired effect */
 
         count = fread(&c, 1, 1, f);
         fclose(f);
-        return count != 1;
+
+        /* Kernel threads have an empty cmdline */
+        if (count <= 0)
+                return true;
+
+        /* Processes with argv[0][0] = '@' we ignore from the killing
+         * spree. */
+        if (count == 1 && c == '@')
+                return true;
+
+        return false;
 }
 
 static int killall(int sign) {
 }
 
 static int killall(int sign) {
@@ -77,7 +93,8 @@ static int killall(int sign) {
         struct dirent *d;
         unsigned int n_processes = 0;
 
         struct dirent *d;
         unsigned int n_processes = 0;
 
-        if ((dir = opendir("/proc")) == NULL)
+        dir = opendir("/proc");
+        if (!dir)
                 return -errno;
 
         while ((d = readdir(dir))) {
                 return -errno;
 
         while ((d = readdir(dir))) {
@@ -86,9 +103,6 @@ static int killall(int sign) {
                 if (parse_pid(d->d_name, &pid) < 0)
                         continue;
 
                 if (parse_pid(d->d_name, &pid) < 0)
                         continue;
 
-                if (is_kernel_thread(pid))
-                        continue;
-
                 if (ignore_proc(pid))
                         continue;
 
                 if (ignore_proc(pid))
                         continue;