]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/process-util.c
util-lib: split out allocation calls into alloc-util.[ch]
[thirdparty/systemd.git] / src / basic / process-util.c
index cfc876567dc2d16248174809b48f3a77a62d04e9..c534656c970ed57d8866631fae782698e8ef8b28 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdbool.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdio.h>
 #include <assert.h>
+#include <ctype.h>
 #include <errno.h>
-#include <unistd.h>
-#include <sys/wait.h>
 #include <signal.h>
-#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
+#include "alloc-util.h"
+#include "escape.h"
+#include "fd-util.h"
 #include "fileio.h"
-#include "util.h"
+#include "fs-util.h"
 #include "log.h"
-#include "signal-util.h"
 #include "process-util.h"
+#include "signal-util.h"
+#include "string-util.h"
+#include "user-util.h"
+#include "util.h"
 
 int get_process_state(pid_t pid) {
         const char *p;
@@ -43,7 +49,10 @@ int get_process_state(pid_t pid) {
         assert(pid >= 0);
 
         p = procfs_file_alloca(pid, "stat");
+
         r = read_one_line_file(p, &line);
+        if (r == -ENOENT)
+                return -ESRCH;
         if (r < 0)
                 return r;
 
@@ -87,8 +96,11 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
         p = procfs_file_alloca(pid, "cmdline");
 
         f = fopen(p, "re");
-        if (!f)
+        if (!f) {
+                if (errno == ENOENT)
+                        return -ESRCH;
                 return -errno;
+        }
 
         if (max_length == 0) {
                 size_t len = 0, allocated = 0;
@@ -175,15 +187,18 @@ int is_kernel_thread(pid_t pid) {
         bool eof;
         FILE *f;
 
-        if (pid == 0)
+        if (pid == 0 || pid == 1) /* pid 1, and we ourselves certainly aren't a kernel thread */
                 return 0;
 
-        assert(pid > 0);
+        assert(pid > 1);
 
         p = procfs_file_alloca(pid, "cmdline");
         f = fopen(p, "re");
-        if (!f)
+        if (!f) {
+                if (errno == ENOENT)
+                        return -ESRCH;
                 return -errno;
+        }
 
         count = fread(&c, 1, 1, f);
         eof = feof(f);
@@ -199,13 +214,18 @@ int is_kernel_thread(pid_t pid) {
 
 int get_process_capeff(pid_t pid, char **capeff) {
         const char *p;
+        int r;
 
         assert(capeff);
         assert(pid >= 0);
 
         p = procfs_file_alloca(pid, "status");
 
-        return get_status_field(p, "\nCapEff:", capeff);
+        r = get_proc_field(p, "CapEff", WHITESPACE, capeff);
+        if (r == -ENOENT)
+                return -ESRCH;
+
+        return r;
 }
 
 static int get_process_link_contents(const char *proc_file, char **name) {
@@ -215,8 +235,10 @@ static int get_process_link_contents(const char *proc_file, char **name) {
         assert(name);
 
         r = readlink_malloc(proc_file, name);
+        if (r == -ENOENT)
+                return -ESRCH;
         if (r < 0)
-                return r == -ENOENT ? -ESRCH : r;
+                return r;
 
         return 0;
 }
@@ -253,8 +275,11 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
 
         p = procfs_file_alloca(pid, "status");
         f = fopen(p, "re");
-        if (!f)
+        if (!f) {
+                if (errno == ENOENT)
+                        return -ESRCH;
                 return -errno;
+        }
 
         FOREACH_LINE(line, f, return -errno) {
                 char *l;
@@ -316,8 +341,11 @@ int get_process_environ(pid_t pid, char **env) {
         p = procfs_file_alloca(pid, "environ");
 
         f = fopen(p, "re");
-        if (!f)
+        if (!f) {
+                if (errno == ENOENT)
+                        return -ESRCH;
                 return -errno;
+        }
 
         while ((c = fgetc(f)) != EOF) {
                 if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
@@ -329,7 +357,13 @@ int get_process_environ(pid_t pid, char **env) {
                         sz += cescape_char(c, outcome + sz);
         }
 
-        outcome[sz] = '\0';
+        if (!outcome) {
+                outcome = strdup("");
+                if (!outcome)
+                        return -ENOMEM;
+        } else
+                outcome[sz] = '\0';
+
         *env = outcome;
         outcome = NULL;
 
@@ -352,6 +386,8 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
 
         p = procfs_file_alloca(pid, "stat");
         r = read_one_line_file(p, &line);
+        if (r == -ENOENT)
+                return -ESRCH;
         if (r < 0)
                 return r;
 
@@ -446,6 +482,16 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_cod
         return -EPROTO;
 }
 
+void sigkill_wait(pid_t *pid) {
+        if (!pid)
+                return;
+        if (*pid <= 1)
+                return;
+
+        if (kill(*pid, SIGKILL) > 0)
+                (void) wait_for_terminate(*pid, NULL);
+}
+
 int kill_and_sigcont(pid_t pid, int sig) {
         int r;
 
@@ -472,8 +518,11 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
         path = procfs_file_alloca(pid, "environ");
 
         f = fopen(path, "re");
-        if (!f)
+        if (!f) {
+                if (errno == ENOENT)
+                        return -ESRCH;
                 return -errno;
+        }
 
         l = strlen(field);
         r = 0;
@@ -532,8 +581,17 @@ bool pid_is_alive(pid_t pid) {
                 return false;
 
         r = get_process_state(pid);
-        if (r == -ENOENT || r == 'Z')
+        if (r == -ESRCH || r == 'Z')
                 return false;
 
         return true;
 }
+
+bool is_main_thread(void) {
+        static thread_local int cached = 0;
+
+        if (_unlikely_(cached == 0))
+                cached = getpid() == gettid() ? 1 : -1;
+
+        return cached > 0;
+}