diff options
Diffstat (limited to 'src/basic/process-util.c')
-rw-r--r-- | src/basic/process-util.c | 53 |
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(); } |