mirror of
https://github.com/systemd/systemd.git
synced 2025-03-19 22:50:17 +03:00
pidfd: cache our own pidfd inode id, and use it at various places (#36060)
This is split out of and preparation for #35224, but makes a ton of sense on its own
This commit is contained in:
commit
9bfc13e93a
6
TODO
6
TODO
@ -218,9 +218,9 @@ Features:
|
||||
be established on top of dm-crypt or dm-verity devices, or an allowlist of
|
||||
file systems (which should probably include vfat, for compat with the ESP)
|
||||
|
||||
* $LISTEN_PID, $MAINPID and $SYSTEMD_EXECPID env vars that the service manager
|
||||
sets should be augmented with $LISTEN_PIDFDID, $MAINPIDFDID and
|
||||
$SYSTEMD_EXECPIDFD (and similar for other env vars we might send).
|
||||
* $LISTEN_PID, $SYSTEMD_EXECPID env vars that the service manager sets should
|
||||
be augmented with $LISTEN_PIDFDID, and $SYSTEMD_EXECPIDFD (and similar for
|
||||
other env vars we might send).
|
||||
|
||||
* port copy.c over to use LabelOps for all labelling.
|
||||
|
||||
|
@ -3886,22 +3886,40 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
|
||||
<varlistentry>
|
||||
<term><varname>$MAINPID</varname></term>
|
||||
|
||||
<listitem><para>The PID of the unit's main process if it is
|
||||
known. This is only set for control processes as invoked by
|
||||
<varname>ExecReload=</varname> and similar.</para>
|
||||
<listitem><para>The UNIX process ID (PID) of the unit's main process if it is known. This is only
|
||||
set for control processes as invoked by <varname>ExecReload=</varname> and similar.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v209"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>$MAINPIDFDID</varname></term>
|
||||
|
||||
<listitem><para>The 64bit inode ID of the file descriptor returned by <citerefentry
|
||||
project='man-pages'><refentrytitle>pidfd_open</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
for the main process (if supported). This is only set for control processes as invoked by
|
||||
<varname>ExecReload=</varname> and similar.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>$MANAGERPID</varname></term>
|
||||
|
||||
<listitem><para>The PID of the user <command>systemd</command>
|
||||
instance, set for processes spawned by it.</para>
|
||||
|
||||
<listitem><para>The PID of the per-user <command>systemd</command> service manager instance, set
|
||||
for processes spawned by it.</para>
|
||||
<xi:include href="version-info.xml" xpointer="v208"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>$MANAGERPIDFDID</varname></term>
|
||||
|
||||
<listitem><para>The <function>pidfd_open()</function> inode ID (see above) of the per-user
|
||||
<command>systemd</command> service manager instance, set for processes spawned by it.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>$LISTEN_FDS</varname></term>
|
||||
<term><varname>$LISTEN_PID</varname></term>
|
||||
|
@ -377,6 +377,7 @@ possible_common_cc_flags = [
|
||||
'-Warray-bounds=2',
|
||||
'-Wdate-time',
|
||||
'-Wendif-labels',
|
||||
'-Werror=discarded-qualifiers',
|
||||
'-Werror=format=2',
|
||||
'-Werror=format-signedness',
|
||||
'-Werror=implicit-function-declaration',
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "macro.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_magic.h"
|
||||
#include "missing_threads.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pidfd-util.h"
|
||||
@ -18,16 +19,14 @@
|
||||
|
||||
static int have_pidfs = -1;
|
||||
|
||||
static int pidfd_check_pidfs(void) {
|
||||
static int pidfd_check_pidfs(int pid_fd) {
|
||||
|
||||
/* NB: the passed fd *must* be acquired via pidfd_open(), i.e. must be a true pidfd! */
|
||||
|
||||
if (have_pidfs >= 0)
|
||||
return have_pidfs;
|
||||
|
||||
_cleanup_close_ int fd = pidfd_open(getpid_cached(), 0);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
return (have_pidfs = fd_is_fs_type(fd, PID_FS_MAGIC));
|
||||
return (have_pidfs = fd_is_fs_type(pid_fd, PID_FS_MAGIC));
|
||||
}
|
||||
|
||||
int pidfd_get_namespace(int fd, unsigned long ns_type_cmd) {
|
||||
@ -231,7 +230,7 @@ int pidfd_get_inode_id(int fd, uint64_t *ret) {
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
r = pidfd_check_pidfs();
|
||||
r = pidfd_check_pidfs(fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
@ -245,3 +244,32 @@ int pidfd_get_inode_id(int fd, uint64_t *ret) {
|
||||
*ret = (uint64_t) st.st_ino;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pidfd_get_inode_id_self_cached(uint64_t *ret) {
|
||||
static thread_local uint64_t cached = 0;
|
||||
static thread_local pid_t initialized = 0; /* < 0: cached error; == 0: invalid; > 0: valid and pid that was current */
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (initialized == getpid_cached()) {
|
||||
*ret = cached;
|
||||
return 0;
|
||||
}
|
||||
if (initialized < 0)
|
||||
return initialized;
|
||||
|
||||
_cleanup_close_ int fd = pidfd_open(getpid_cached(), 0);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
r = pidfd_get_inode_id(fd, &cached);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return (initialized = -EOPNOTSUPP);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = cached;
|
||||
initialized = getpid_cached();
|
||||
return 0;
|
||||
}
|
||||
|
@ -17,3 +17,5 @@ int pidfd_get_uid(int fd, uid_t *ret);
|
||||
int pidfd_get_cgroupid(int fd, uint64_t *ret);
|
||||
|
||||
int pidfd_get_inode_id(int fd, uint64_t *ret);
|
||||
|
||||
int pidfd_get_inode_id_self_cached(uint64_t *ret);
|
||||
|
@ -83,14 +83,17 @@ bool pidref_equal(PidRef *a, PidRef *b) {
|
||||
}
|
||||
|
||||
int pidref_set_pid(PidRef *pidref, pid_t pid) {
|
||||
uint64_t pidfdid = 0;
|
||||
int fd;
|
||||
|
||||
assert(pidref);
|
||||
|
||||
if (pid < 0)
|
||||
return -ESRCH;
|
||||
if (pid == 0)
|
||||
if (pid == 0) {
|
||||
pid = getpid_cached();
|
||||
(void) pidfd_get_inode_id_self_cached(&pidfdid);
|
||||
}
|
||||
|
||||
fd = pidfd_open(pid, 0);
|
||||
if (fd < 0) {
|
||||
@ -104,6 +107,7 @@ int pidref_set_pid(PidRef *pidref, pid_t pid) {
|
||||
*pidref = (PidRef) {
|
||||
.fd = fd,
|
||||
.pid = pid,
|
||||
.fd_id = pidfdid,
|
||||
};
|
||||
|
||||
return 0;
|
||||
@ -388,17 +392,32 @@ int pidref_verify(const PidRef *pidref) {
|
||||
return 1; /* We have a pidfd and it still points to the PID we have, hence all is *really* OK → return 1 */
|
||||
}
|
||||
|
||||
bool pidref_is_self(const PidRef *pidref) {
|
||||
if (!pidref)
|
||||
bool pidref_is_self(PidRef *pidref) {
|
||||
if (!pidref_is_set(pidref))
|
||||
return false;
|
||||
|
||||
if (pidref_is_remote(pidref))
|
||||
return false;
|
||||
|
||||
return pidref->pid == getpid_cached();
|
||||
if (pidref->pid != getpid_cached())
|
||||
return false;
|
||||
|
||||
/* PID1 cannot exit, hence no point in comparing pidfd IDs, they can never change */
|
||||
if (pidref->pid == 1)
|
||||
return true;
|
||||
|
||||
/* Also compare pidfd ID if we can get it */
|
||||
if (pidref_acquire_pidfd_id(pidref) < 0)
|
||||
return true;
|
||||
|
||||
uint64_t self_id;
|
||||
if (pidfd_get_inode_id_self_cached(&self_id) < 0)
|
||||
return true;
|
||||
|
||||
return pidref->fd_id == self_id;
|
||||
}
|
||||
|
||||
int pidref_wait(const PidRef *pidref, siginfo_t *ret, int options) {
|
||||
int pidref_wait(PidRef *pidref, siginfo_t *ret, int options) {
|
||||
int r;
|
||||
|
||||
if (!pidref_is_set(pidref))
|
||||
@ -424,7 +443,7 @@ int pidref_wait(const PidRef *pidref, siginfo_t *ret, int options) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pidref_wait_for_terminate(const PidRef *pidref, siginfo_t *ret) {
|
||||
int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret) {
|
||||
int r;
|
||||
|
||||
for (;;) {
|
||||
|
@ -39,7 +39,7 @@ struct PidRef {
|
||||
their own pidfs and each process comes with a unique inode number */
|
||||
};
|
||||
|
||||
#define PIDREF_NULL (const PidRef) { .fd = -EBADF }
|
||||
#define PIDREF_NULL (PidRef) { .fd = -EBADF }
|
||||
|
||||
/* A special pidref value that we are using when a PID shall be automatically acquired from some surrounding
|
||||
* context, for example connection peer. Much like PIDREF_NULL it will be considered unset by
|
||||
@ -77,7 +77,7 @@ static inline int pidref_set_self(PidRef *pidref) {
|
||||
return pidref_set_pid(pidref, 0);
|
||||
}
|
||||
|
||||
bool pidref_is_self(const PidRef *pidref);
|
||||
bool pidref_is_self(PidRef *pidref);
|
||||
|
||||
void pidref_done(PidRef *pidref);
|
||||
PidRef* pidref_free(PidRef *pidref);
|
||||
@ -92,8 +92,8 @@ int pidref_kill(const PidRef *pidref, int sig);
|
||||
int pidref_kill_and_sigcont(const PidRef *pidref, int sig);
|
||||
int pidref_sigqueue(const PidRef *pidref, int sig, int value);
|
||||
|
||||
int pidref_wait(const PidRef *pidref, siginfo_t *siginfo, int options);
|
||||
int pidref_wait_for_terminate(const PidRef *pidref, siginfo_t *ret);
|
||||
int pidref_wait(PidRef *pidref, siginfo_t *siginfo, int options);
|
||||
int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret);
|
||||
|
||||
static inline void pidref_done_sigkill_wait(PidRef *pidref) {
|
||||
if (!pidref_is_set(pidref))
|
||||
|
@ -1120,7 +1120,7 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pidref_is_my_child(const PidRef *pid) {
|
||||
int pidref_is_my_child(PidRef *pid) {
|
||||
int r;
|
||||
|
||||
if (!pidref_is_set(pid))
|
||||
@ -1150,7 +1150,7 @@ int pid_is_my_child(pid_t pid) {
|
||||
return pidref_is_my_child(&PIDREF_MAKE_FROM_PID(pid));
|
||||
}
|
||||
|
||||
int pidref_is_unwaited(const PidRef *pid) {
|
||||
int pidref_is_unwaited(PidRef *pid) {
|
||||
int r;
|
||||
|
||||
/* Checks whether a PID is still valid at all, including a zombie */
|
||||
|
@ -90,9 +90,9 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value);
|
||||
int pid_is_alive(pid_t pid);
|
||||
int pidref_is_alive(const PidRef *pidref);
|
||||
int pid_is_unwaited(pid_t pid);
|
||||
int pidref_is_unwaited(const PidRef *pidref);
|
||||
int pidref_is_unwaited(PidRef *pidref);
|
||||
int pid_is_my_child(pid_t pid);
|
||||
int pidref_is_my_child(const PidRef *pidref);
|
||||
int pidref_is_my_child(PidRef *pidref);
|
||||
int pidref_from_same_root_fs(PidRef *a, PidRef *b);
|
||||
|
||||
bool is_main_thread(void);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "missing_syscall.h"
|
||||
#include "missing_threads.h"
|
||||
#include "parse-util.h"
|
||||
#include "pidfd-util.h"
|
||||
#include "process-util.h"
|
||||
#include "random-util.h"
|
||||
#include "sha256.h"
|
||||
@ -39,6 +40,7 @@ static void fallback_random_bytes(void *p, size_t n) {
|
||||
uint64_t call_id, block_id;
|
||||
usec_t stamp_mono, stamp_real;
|
||||
pid_t pid, tid;
|
||||
uint64_t pidfdid;
|
||||
uint8_t auxval[16];
|
||||
} state = {
|
||||
/* Arbitrary domain separation to prevent other usage of AT_RANDOM from clashing. */
|
||||
@ -51,6 +53,7 @@ static void fallback_random_bytes(void *p, size_t n) {
|
||||
|
||||
memcpy(state.label, "systemd fallback random bytes v1", sizeof(state.label));
|
||||
memcpy(state.auxval, ULONG_TO_PTR(getauxval(AT_RANDOM)), sizeof(state.auxval));
|
||||
(void) pidfd_get_inode_id_self_cached(&state.pidfdid);
|
||||
|
||||
while (n > 0) {
|
||||
struct sha256_ctx ctx;
|
||||
|
@ -4482,7 +4482,7 @@ Unit *manager_get_unit_by_pidref_watching(Manager *m, const PidRef *pid) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Unit *manager_get_unit_by_pidref(Manager *m, const PidRef *pid) {
|
||||
Unit* manager_get_unit_by_pidref(Manager *m, PidRef *pid) {
|
||||
Unit *u;
|
||||
|
||||
assert(m);
|
||||
|
@ -466,7 +466,7 @@ unsigned manager_dispatch_cgroup_realize_queue(Manager *m);
|
||||
Unit *manager_get_unit_by_cgroup(Manager *m, const char *cgroup);
|
||||
Unit *manager_get_unit_by_pidref_cgroup(Manager *m, const PidRef *pid);
|
||||
Unit *manager_get_unit_by_pidref_watching(Manager *m, const PidRef *pid);
|
||||
Unit* manager_get_unit_by_pidref(Manager *m, const PidRef *pid);
|
||||
Unit* manager_get_unit_by_pidref(Manager *m, PidRef *pid);
|
||||
Unit* manager_get_unit_by_pid(Manager *m, pid_t pid);
|
||||
|
||||
uint64_t unit_get_ancestor_memory_min(Unit *u);
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "open-file.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pidfd-util.h"
|
||||
#include "process-util.h"
|
||||
#include "random-util.h"
|
||||
#include "selinux-util.h"
|
||||
@ -1769,7 +1770,7 @@ static int service_spawn_internal(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
our_env = new0(char*, 13);
|
||||
our_env = new0(char*, 15);
|
||||
if (!our_env)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1781,14 +1782,25 @@ static int service_spawn_internal(
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (pidref_is_set(&s->main_pid))
|
||||
if (pidref_is_set(&s->main_pid)) {
|
||||
if (asprintf(our_env + n_env++, "MAINPID="PID_FMT, s->main_pid.pid) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
if (MANAGER_IS_USER(UNIT(s)->manager))
|
||||
if (pidref_acquire_pidfd_id(&s->main_pid) >= 0)
|
||||
if (asprintf(our_env + n_env++, "MAINPIDFDID=%" PRIu64, s->main_pid.fd_id) < 0)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (MANAGER_IS_USER(UNIT(s)->manager)) {
|
||||
if (asprintf(our_env + n_env++, "MANAGERPID="PID_FMT, getpid_cached()) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
uint64_t pidfdid;
|
||||
if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0)
|
||||
if (asprintf(our_env + n_env++, "MANAGERPIDFDID=%" PRIu64, pidfdid) < 0)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (s->pid_file)
|
||||
if (asprintf(our_env + n_env++, "PIDFILE=%s", s->pid_file) < 0)
|
||||
return -ENOMEM;
|
||||
|
@ -6007,7 +6007,7 @@ bool unit_needs_console(Unit *u) {
|
||||
return exec_context_may_touch_console(ec);
|
||||
}
|
||||
|
||||
int unit_pid_attachable(Unit *u, const PidRef *pid, sd_bus_error *error) {
|
||||
int unit_pid_attachable(Unit *u, PidRef *pid, sd_bus_error *error) {
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
@ -1004,7 +1004,7 @@ int unit_warn_leftover_processes(Unit *u, bool start);
|
||||
|
||||
bool unit_needs_console(Unit *u);
|
||||
|
||||
int unit_pid_attachable(Unit *unit, const PidRef *pid, sd_bus_error *error);
|
||||
int unit_pid_attachable(Unit *unit, PidRef *pid, sd_bus_error *error);
|
||||
|
||||
static inline bool unit_has_job_type(Unit *u, JobType type) {
|
||||
return u && u->job && u->job->type == type;
|
||||
|
@ -80,28 +80,49 @@ static int help(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pid_t manager_pid(void) {
|
||||
const char *e;
|
||||
pid_t pid;
|
||||
static int get_manager_pid(PidRef *ret) {
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* If we run as a service managed by systemd --user the $MANAGERPID environment variable points to
|
||||
* the service manager's PID. */
|
||||
e = getenv("MANAGERPID");
|
||||
if (!e)
|
||||
return 0;
|
||||
|
||||
r = parse_pid(e, &pid);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "$MANAGERPID is set to an invalid PID, ignoring: %s", e);
|
||||
const char *e = getenv("MANAGERPID");
|
||||
if (!e) {
|
||||
*ret = PIDREF_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pid;
|
||||
_cleanup_(pidref_done) PidRef manager = PIDREF_NULL;
|
||||
r = pidref_set_pidstr(&manager, e);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "$MANAGERPID is set to an invalid PID, ignoring: %s", e);
|
||||
|
||||
e = getenv("MANAGERPIDFDID");
|
||||
if (e) {
|
||||
uint64_t manager_pidfd_id;
|
||||
|
||||
r = safe_atou64(e, &manager_pidfd_id);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "$MANAGERPIDFDID is not set to a valid inode number, ignoring: %s", e);
|
||||
|
||||
r = pidref_acquire_pidfd_id(&manager);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Unable to acquire pidfd ID for manager: %m");
|
||||
|
||||
if (manager_pidfd_id != manager.fd_id) {
|
||||
log_debug("$MANAGERPIDFDID doesn't match process currently referenced by $MANAGERPID, suppressing.");
|
||||
*ret = PIDREF_NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*ret = TAKE_PIDREF(manager);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pidref_parent_if_applicable(PidRef *ret) {
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL, manager = PIDREF_NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
@ -112,12 +133,18 @@ static int pidref_parent_if_applicable(PidRef *ret) {
|
||||
|
||||
/* Don't send from PID 1 or the service manager's PID (which might be distinct from 1, if we are a
|
||||
* --user service). That'd just be confusing for the service manager. */
|
||||
if (pidref.pid <= 1 ||
|
||||
pidref.pid == manager_pid())
|
||||
return pidref_set_self(ret);
|
||||
if (pidref.pid == 1)
|
||||
goto from_self;
|
||||
|
||||
r = get_manager_pid(&manager);
|
||||
if (r > 0 && pidref_equal(&pidref, &manager))
|
||||
goto from_self;
|
||||
|
||||
*ret = TAKE_PIDREF(pidref);
|
||||
return 0;
|
||||
|
||||
from_self:
|
||||
return pidref_set_self(ret);
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
|
@ -7,8 +7,6 @@
|
||||
#include "stdio-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
#define PIDREF_NULL_NONCONST (PidRef) { .fd = -EBADF }
|
||||
|
||||
TEST(pidref_is_set) {
|
||||
assert_se(!pidref_is_set(NULL));
|
||||
assert_se(!pidref_is_set(&PIDREF_NULL));
|
||||
@ -17,14 +15,14 @@ TEST(pidref_is_set) {
|
||||
|
||||
TEST(pidref_equal) {
|
||||
assert_se(pidref_equal(NULL, NULL));
|
||||
assert_se(pidref_equal(NULL, &PIDREF_NULL_NONCONST));
|
||||
assert_se(pidref_equal(&PIDREF_NULL_NONCONST, NULL));
|
||||
assert_se(pidref_equal(&PIDREF_NULL_NONCONST, &PIDREF_NULL_NONCONST));
|
||||
assert_se(pidref_equal(NULL, &PIDREF_NULL));
|
||||
assert_se(pidref_equal(&PIDREF_NULL, NULL));
|
||||
assert_se(pidref_equal(&PIDREF_NULL, &PIDREF_NULL));
|
||||
|
||||
assert_se(!pidref_equal(NULL, &PIDREF_MAKE_FROM_PID(1)));
|
||||
assert_se(!pidref_equal(&PIDREF_MAKE_FROM_PID(1), NULL));
|
||||
assert_se(!pidref_equal(&PIDREF_NULL_NONCONST, &PIDREF_MAKE_FROM_PID(1)));
|
||||
assert_se(!pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_NULL_NONCONST));
|
||||
assert_se(!pidref_equal(&PIDREF_NULL, &PIDREF_MAKE_FROM_PID(1)));
|
||||
assert_se(!pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_NULL));
|
||||
assert_se(pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_MAKE_FROM_PID(1)));
|
||||
assert_se(!pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_MAKE_FROM_PID(2)));
|
||||
}
|
||||
@ -231,7 +229,7 @@ TEST(pidref_is_remote) {
|
||||
assert_se(!pidref_is_remote(&PIDREF_MAKE_FROM_PID(getpid_cached())));
|
||||
assert_se(!pidref_is_remote(&PIDREF_AUTOMATIC));
|
||||
|
||||
static const PidRef p = {
|
||||
PidRef p = {
|
||||
.pid = 1,
|
||||
.fd = -EREMOTE,
|
||||
.fd_id = 4711,
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "missing_syscall.h"
|
||||
#include "namespace-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "pidfd-util.h"
|
||||
#include "process-util.h"
|
||||
#include "procfs-util.h"
|
||||
#include "rlimit-util.h"
|
||||
@ -1065,6 +1066,21 @@ TEST(pidref_from_same_root_fs) {
|
||||
ASSERT_OK_ZERO(pidref_from_same_root_fs(&child2, &self));
|
||||
}
|
||||
|
||||
TEST(pidfd_get_inode_id_self_cached) {
|
||||
int r;
|
||||
|
||||
log_info("pid=" PID_FMT, getpid_cached());
|
||||
|
||||
uint64_t id;
|
||||
r = pidfd_get_inode_id_self_cached(&id);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
log_info("pidfdid not supported");
|
||||
else {
|
||||
assert(r >= 0);
|
||||
log_info("pidfdid=%" PRIu64, id);
|
||||
}
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
log_show_color(true);
|
||||
return EXIT_SUCCESS;
|
||||
|
Loading…
x
Reference in New Issue
Block a user