summaryrefslogtreecommitdiffstats
path: root/src/basic/process-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/process-util.c')
-rw-r--r--src/basic/process-util.c53
1 files changed, 46 insertions, 7 deletions
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 0367270724..21e296864a 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -1228,18 +1228,53 @@ int pidref_is_alive(const PidRef *pidref) {
return result;
}
-int pid_from_same_root_fs(pid_t pid) {
- const char *root;
+int pidref_from_same_root_fs(PidRef *a, PidRef *b) {
+ _cleanup_(pidref_done) PidRef self = PIDREF_NULL;
+ int r;
- if (pid < 0)
+ /* Checks if the two specified processes have the same root fs. Either can be specified as NULL in
+ * which case we'll check against ourselves. */
+
+ if (!a || !b) {
+ r = pidref_set_self(&self);
+ if (r < 0)
+ return r;
+ if (!a)
+ a = &self;
+ if (!b)
+ b = &self;
+ }
+
+ if (!pidref_is_set(a) || !pidref_is_set(b))
+ return -ESRCH;
+
+ /* If one of the two processes have the same root they cannot have the same root fs, but if both of
+ * them do we don't know */
+ if (pidref_is_remote(a) && pidref_is_remote(b))
+ return -EREMOTE;
+ if (pidref_is_remote(a) || pidref_is_remote(b))
return false;
- if (pid == 0 || pid == getpid_cached())
+ if (pidref_equal(a, b))
return true;
- root = procfs_file_alloca(pid, "root");
+ const char *roota = procfs_file_alloca(a->pid, "root");
+ const char *rootb = procfs_file_alloca(b->pid, "root");
- return inode_same(root, "/proc/1/root", 0);
+ int result = inode_same(roota, rootb, 0);
+ if (result == -ENOENT)
+ return proc_mounted() == 0 ? -ENOSYS : -ESRCH;
+ if (result < 0)
+ return result;
+
+ r = pidref_verify(a);
+ if (r < 0)
+ return r;
+ r = pidref_verify(b);
+ if (r < 0)
+ return r;
+
+ return result;
}
bool is_main_thread(void) {
@@ -1763,6 +1798,9 @@ int safe_fork_full(
}
}
+ if (FLAGS_SET(flags, FORK_FREEZE))
+ freeze();
+
if (ret_pid)
*ret_pid = getpid_cached();
@@ -1959,7 +1997,8 @@ _noreturn_ void freeze(void) {
break;
}
- /* waitid() failed with an unexpected error, things are really borked. Freeze now! */
+ /* waitid() failed with an ECHLD error (because there are no left-over child processes) or any other
+ * (unexpected) error. Freeze for good now! */
for (;;)
pause();
}