• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 20401947236

20 Dec 2025 09:56PM UTC coverage: 72.701% (+0.1%) from 72.578%
20401947236

push

github

DaanDeMeyer
core/socket: modernize listen/accept_in_cgroup

4 of 9 new or added lines in 1 file covered. (44.44%)

7723 existing lines in 114 files now uncovered.

309972 of 426363 relevant lines covered (72.7%)

1133403.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.0
/src/basic/pidref.h
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
#pragma once
3

4
#include <signal.h>
5

6
#include "basic-forward.h"
7

8
/* An embeddable structure carrying a reference to a process. Supposed to be used when tracking processes
9
 * continuously. This combines a PID, a modern Linux pidfd and the 64bit inode number of the pidfd into one
10
 * structure. Note that depending on kernel support the pidfd might not be initialized, and if it is
11
 * initialized then fd_id might still not be initialized (because the concept was added to the kernel much
12
 * later than pidfds themselves).
13
 *
14
 * There are three special states a PidRef can be in:
15
 *
16
 * 1. It can be *unset*. Use pidref_is_set() to detect this case. Most operations attempted on such a PidRef
17
 *    will fail with -ESRCH. Use PIDREF_NULL for initializing a PidRef in this state.
18
 *
19
 * 2. It can be marked as *automatic*. This is a special state indicating that a process reference is
20
 *    supposed to be derived automatically from the current context. This is used by the Varlink/JSON
21
 *    dispatcher as indication that a PidRef shall be derived from the connection peer, but might be
22
 *    otherwise used too. When marked *automatic* the PidRef will also be considered *unset*, hence most
23
 *    operations will fail with -ESRCH, as above.
24
 *
25
 * 3. It can be marked as *remote*. This is useful when deserializing a PidRef structure from an IPC message
26
 *    or similar, and it has been determined that the given PID definitely doesn't refer to a local
27
 *    process. In this case the PidRef logic will refrain from trying to acquire a pidfd for the
28
 *    process. Moreover, most operations will fail with -EREMOTE. Only PidRef structures that are not marked
29
 *    *unset* can be marked *remote*.
30
 */
31
typedef struct PidRef {
32
        pid_t pid;      /* > 0 if the PidRef is set, otherwise set to INT_MIN (PID_AUTOMATIC) if automatic
33
                         * mode is desired, or 0 otherwise. */
34
        int fd;         /* only valid if pidfd are available in the kernel, and we manage to get an fd. If we
35
                         * know that the PID is not from the local machine we set this to -EREMOTE, otherwise
36
                         * we use -EBADF as indicator the fd is invalid. */
37
        uint64_t fd_id; /* the inode number of pidfd. only useful in kernel 6.9+ where pidfds live in
38
                           their own pidfs and each process comes with a unique inode number */
39
} PidRef;
40

41
#define PIDREF_NULL (PidRef) { .fd = -EBADF }
42

43
/* A special pidref value that we are using when a PID shall be automatically acquired from some surrounding
44
 * context, for example connection peer. Much like PIDREF_NULL it will be considered unset by
45
 * pidref_is_set(). */
46
#define PIDREF_AUTOMATIC (const PidRef) { .pid = (pid_t) INT_MIN, .fd = -EBADF }
47

48
/* Turns a pid_t into a PidRef structure on-the-fly *without* acquiring a pidfd for it. (As opposed to
49
 * pidref_set_pid() which does so *with* acquiring one, see below) */
50
#define PIDREF_MAKE_FROM_PID(x) (PidRef) { .pid = (x), .fd = -EBADF }
51

52
static inline bool pidref_is_set(const PidRef *pidref) {
1,132,080✔
53
        return pidref && pidref->pid > 0;
1,431,638✔
54
}
55

56
bool pidref_is_automatic(const PidRef *pidref);
57

58
static inline bool pidref_is_set_or_automatic(const PidRef *pidref) {
1✔
59
        return pidref_is_set(pidref) || pidref_is_automatic(pidref);
2✔
60
}
61

62
static inline bool pidref_is_remote(const PidRef *pidref) {
146,133✔
63
        /* If the fd is set to -EREMOTE we assume PidRef does not refer to a local PID, but on another
64
         * machine (and we just got the PidRef initialized due to deserialization of some RPC message) */
65
        return pidref_is_set(pidref) && pidref->fd == -EREMOTE;
490,090✔
66
}
67

68
int pidref_acquire_pidfd_id(PidRef *pidref);
69
bool pidref_equal(PidRef *a, PidRef *b);
70

71
/* This turns a pid_t into a PidRef structure, and acquires a pidfd for it, if possible. (As opposed to
72
 * PIDREF_MAKE_FROM_PID() above, which does not acquire a pidfd.) */
73
int pidref_set_pid(PidRef *pidref, pid_t pid);
74
int pidref_set_pidstr(PidRef *pidref, const char *pid);
75
int pidref_set_pid_and_pidfd_id(PidRef *pidref, pid_t pid, uint64_t pidfd_id);
76
int pidref_set_pidfd(PidRef *pidref, int fd);
77
int pidref_set_pidfd_take(PidRef *pidref, int fd); /* takes ownership of the passed pidfd on success */
78
int pidref_set_pidfd_consume(PidRef *pidref, int fd); /* takes ownership of the passed pidfd in both success and failure */
79
int pidref_set_parent(PidRef *ret);
80
static inline int pidref_set_self(PidRef *pidref) {
31,581✔
81
        return pidref_set_pid(pidref, 0);
31,581✔
82
}
83

84
bool pidref_is_self(PidRef *pidref);
85

86
void pidref_done(PidRef *pidref);
87
PidRef* pidref_free(PidRef *pidref);
88
DEFINE_TRIVIAL_CLEANUP_FUNC(PidRef*, pidref_free);
13,621✔
89

90
int pidref_copy(const PidRef *pidref, PidRef *ret);
91
int pidref_dup(const PidRef *pidref, PidRef **ret);
92

93
int pidref_new_from_pid(pid_t pid, PidRef **ret);
94

95
int pidref_kill(const PidRef *pidref, int sig);
96
int pidref_kill_and_sigcont(const PidRef *pidref, int sig);
97
int pidref_sigqueue(const PidRef *pidref, int sig, int value);
98

99
int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *ret_si);
100
static inline int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret_si) {
10,855✔
101
        return pidref_wait_for_terminate_full(pidref, USEC_INFINITY, ret_si);
10,848✔
102
}
103

104
static inline void pidref_done_sigterm_wait(PidRef *pidref) {
591,461✔
105
        if (!pidref_is_set(pidref))
591,461✔
106
                return;
107

108
        (void) pidref_kill(pidref, SIGTERM);
96✔
109
        (void) pidref_wait_for_terminate(pidref, NULL);
96✔
110
        pidref_done(pidref);
96✔
111
}
112

113
static inline void pidref_done_sigkill_wait(PidRef *pidref) {
25,903✔
114
        if (!pidref_is_set(pidref))
25,903✔
115
                return;
116

117
        (void) pidref_kill(pidref, SIGKILL);
3,285✔
118
        (void) pidref_wait_for_terminate(pidref, NULL);
3,285✔
119
        pidref_done(pidref);
3,285✔
120
}
121

UNCOV
122
static inline void pidref_done_sigkill_nowait(PidRef *pidref) {
×
UNCOV
123
        if (!pidref_is_set(pidref))
×
124
                return;
125

UNCOV
126
        (void) pidref_kill(pidref, SIGKILL);
×
UNCOV
127
        pidref_done(pidref);
×
128
}
129

130
int pidref_verify(const PidRef *pidref);
131

132
#define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL)
133

134
struct siphash;
135
void pidref_hash_func(const PidRef *pidref, struct siphash *state);
136
int pidref_compare_func(const PidRef *a, const PidRef *b);
137

138
extern const struct hash_ops pidref_hash_ops;
139
extern const struct hash_ops pidref_hash_ops_free; /* Has destructor call for pidref_free(), i.e. expects heap allocated PidRef as keys */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc