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

systemd / systemd / 14630481637

23 Apr 2025 07:04PM UTC coverage: 72.178% (-0.002%) from 72.18%
14630481637

push

github

DaanDeMeyer
mkosi: Run clangd within the tools tree instead of the build container

Running within the build sandbox has a number of disadvantages:
- We have a separate clangd cache for each distribution/release combo
- It requires to build the full image before clangd can be used
- It breaks every time the image becomes out of date and requires a
  rebuild
- We can't look at system headers as we don't have the knowledge to map
  them from inside the build sandbox to the corresponding path on the host

Instead, let's have mkosi.clangd run clangd within the tools tree. We
already require building systemd for both the host and the target anyway,
and all the dependencies to build systemd are installed in the tools tree
already for that, as well as clangd since it's installed together with the
other clang tooling we install in the tools tree. Unlike the previous approach,
this approach only requires the mkosi tools tree to be built upfront, which has
a much higher chance of not invalidating its cache. We can also trivially map
system header lookups from within the sandbox to the path within mkosi.tools
on the host so that starts working as well.

297054 of 411557 relevant lines covered (72.18%)

686269.58 hits per line

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

98.21
/src/core/unit.h
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
#pragma once
3

4
#include <errno.h>
5
#include <stdbool.h>
6
#include <stdlib.h>
7
#include <sys/socket.h>
8
#include <unistd.h>
9

10
#include "sd-id128.h"
11

12
#include "cgroup.h"
13
#include "condition.h"
14
#include "emergency-action.h"
15
#include "execute.h"
16
#include "install.h"
17
#include "job.h"
18
#include "list.h"
19
#include "log-context.h"
20
#include "mount-util.h"
21
#include "pidref.h"
22
#include "ratelimit.h"
23
#include "unit-file.h"
24

25
typedef struct UnitRef UnitRef;
26

27
typedef enum UnitMountDependencyType {
28
        UNIT_MOUNT_WANTS,
29
        UNIT_MOUNT_REQUIRES,
30
        _UNIT_MOUNT_DEPENDENCY_TYPE_MAX,
31
        _UNIT_MOUNT_DEPENDENCY_TYPE_INVALID = -EINVAL,
32
} UnitMountDependencyType;
33

34
typedef enum KillOperation {
35
        KILL_TERMINATE,
36
        KILL_TERMINATE_AND_LOG,
37
        KILL_RESTART,
38
        KILL_KILL,
39
        KILL_WATCHDOG,
40
        _KILL_OPERATION_MAX,
41
        _KILL_OPERATION_INVALID = -EINVAL,
42
} KillOperation;
43

44
typedef enum CollectMode {
45
        COLLECT_INACTIVE,
46
        COLLECT_INACTIVE_OR_FAILED,
47
        _COLLECT_MODE_MAX,
48
        _COLLECT_MODE_INVALID = -EINVAL,
49
} CollectMode;
50

51
typedef enum OOMPolicy {
52
        OOM_CONTINUE,          /* The kernel or systemd-oomd kills the process it wants to kill, and that's it */
53
        OOM_STOP,              /* The kernel or systemd-oomd kills the process it wants to kill, and we stop the unit */
54
        OOM_KILL,              /* The kernel or systemd-oomd kills the process it wants to kill, and all others in the unit, and we stop the unit */
55
        _OOM_POLICY_MAX,
56
        _OOM_POLICY_INVALID = -EINVAL,
57
} OOMPolicy;
58

59
typedef enum StatusType {
60
        STATUS_TYPE_EPHEMERAL,
61
        STATUS_TYPE_NORMAL,
62
        STATUS_TYPE_NOTICE,
63
        STATUS_TYPE_EMERGENCY,
64
} StatusType;
65

66
static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) {
418,992✔
67
        return IN_SET(t, UNIT_ACTIVE, UNIT_RELOADING, UNIT_REFRESHING);
633,170✔
68
}
69

70
static inline bool UNIT_IS_ACTIVE_OR_ACTIVATING(UnitActiveState t) {
465,459✔
71
        return IN_SET(t, UNIT_ACTIVE, UNIT_ACTIVATING, UNIT_RELOADING, UNIT_REFRESHING);
465,459✔
72
}
73

74
static inline bool UNIT_IS_INACTIVE_OR_DEACTIVATING(UnitActiveState t) {
31,082✔
75
        return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED, UNIT_DEACTIVATING);
31,082✔
76
}
77

78
static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) {
1,280,161✔
79
        return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED);
1,685,599✔
80
}
81

82
static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) {
102,450✔
83
        return t >= 0 && t < _UNIT_LOAD_STATE_MAX && !IN_SET(t, UNIT_STUB, UNIT_MERGED);
102,450✔
84
}
85

86
static inline bool UNIT_IS_LOAD_ERROR(UnitLoadState t) {
63,188✔
87
        return IN_SET(t, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR);
63,188✔
88
}
89

90
/* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We
91
 * use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be
92
 * created as a result of multiple "reasons", hence the bitmask. */
93
typedef enum UnitDependencyMask {
94
        /* Configured directly by the unit file, .wants/.requires symlink or drop-in, or as an immediate result of a
95
         * non-dependency option configured that way.  */
96
        UNIT_DEPENDENCY_FILE               = 1 << 0,
97

98
        /* As unconditional implicit dependency (not affected by unit configuration — except by the unit name and
99
         * type) */
100
        UNIT_DEPENDENCY_IMPLICIT           = 1 << 1,
101

102
        /* A dependency effected by DefaultDependencies=yes. Note that dependencies marked this way are conceptually
103
         * just a subset of UNIT_DEPENDENCY_FILE, as DefaultDependencies= is itself a unit file setting that can only
104
         * be set in unit files. We make this two separate bits only to help debugging how dependencies came to be. */
105
        UNIT_DEPENDENCY_DEFAULT            = 1 << 2,
106

107
        /* A dependency created from udev rules */
108
        UNIT_DEPENDENCY_UDEV               = 1 << 3,
109

110
        /* A dependency created because of some unit's RequiresMountsFor= setting */
111
        UNIT_DEPENDENCY_PATH               = 1 << 4,
112

113
        /* A dependency initially configured from the mount unit file however the dependency will be updated
114
         * from /proc/self/mountinfo as soon as the kernel will make the entry for that mount available in
115
         * the /proc file */
116
        UNIT_DEPENDENCY_MOUNT_FILE         = 1 << 5,
117

118
        /* A dependency created or updated because of data read from /proc/self/mountinfo */
119
        UNIT_DEPENDENCY_MOUNTINFO          = 1 << 6,
120

121
        /* A dependency created because of data read from /proc/swaps and no other configuration source */
122
        UNIT_DEPENDENCY_PROC_SWAP          = 1 << 7,
123

124
        /* A dependency for units in slices assigned by directly setting Slice= */
125
        UNIT_DEPENDENCY_SLICE_PROPERTY     = 1 << 8,
126

127
        _UNIT_DEPENDENCY_MASK_FULL         = (1 << 9) - 1,
128
} UnitDependencyMask;
129

130
/* The Unit's dependencies[] hashmaps use this structure as value. It has the same size as a void pointer, and thus can
131
 * be stored directly as hashmap value, without any indirection. Note that this stores two masks, as both the origin
132
 * and the destination of a dependency might have created it. */
133
typedef union UnitDependencyInfo {
134
        void *data;
135
        struct {
136
                UnitDependencyMask origin_mask:16;
137
                UnitDependencyMask destination_mask:16;
138
        } _packed_;
139
} UnitDependencyInfo;
140

141
/* Store information about why a unit was activated.
142
 * We start with trigger units (.path/.timer), eventually it will be expanded to include more metadata. */
143
typedef struct ActivationDetails {
144
        unsigned n_ref;
145
        UnitType trigger_unit_type;
146
        char *trigger_unit_name;
147
} ActivationDetails;
148

149
/* For casting an activation event into the various unit-specific types */
150
#define DEFINE_ACTIVATION_DETAILS_CAST(UPPERCASE, MixedCase, UNIT_TYPE)         \
151
        static inline MixedCase* UPPERCASE(ActivationDetails *a) {              \
152
                if (_unlikely_(!a || a->trigger_unit_type != UNIT_##UNIT_TYPE)) \
153
                        return NULL;                                            \
154
                                                                                \
155
                return (MixedCase*) a;                                          \
156
        }
157

158
/* For casting the various unit types into a unit */
159
#define ACTIVATION_DETAILS(u)                                         \
160
        ({                                                            \
161
                typeof(u) _u_ = (u);                                  \
162
                ActivationDetails *_w_ = _u_ ? &(_u_)->meta : NULL;   \
163
                _w_;                                                  \
164
        })
165

166
ActivationDetails *activation_details_new(Unit *trigger_unit);
167
ActivationDetails *activation_details_ref(ActivationDetails *p);
168
ActivationDetails *activation_details_unref(ActivationDetails *p);
169
void activation_details_serialize(ActivationDetails *p, FILE *f);
170
int activation_details_deserialize(const char *key, const char *value, ActivationDetails **info);
171
int activation_details_append_env(ActivationDetails *info, char ***strv);
172
int activation_details_append_pair(ActivationDetails *info, char ***strv);
173
DEFINE_TRIVIAL_CLEANUP_FUNC(ActivationDetails*, activation_details_unref);
16✔
174

175
typedef struct ActivationDetailsVTable {
176
        /* How much memory does an object of this activation type need */
177
        size_t object_size;
178

179
        /* This should reset all type-specific variables. This should not allocate memory, and is called
180
         * with zero-initialized data. It should hence only initialize variables that need to be set != 0. */
181
        void (*init)(ActivationDetails *info, Unit *trigger_unit);
182

183
        /* This should free all type-specific variables. It should be idempotent. */
184
        void (*done)(ActivationDetails *info);
185

186
        /* This should serialize all type-specific variables. */
187
        void (*serialize)(ActivationDetails *info, FILE *f);
188

189
        /* This should deserialize all type-specific variables, one at a time. */
190
        int (*deserialize)(const char *key, const char *value, ActivationDetails **info);
191

192
        /* This should format the type-specific variables for the env block of the spawned service,
193
         * and return the number of added items. */
194
        int (*append_env)(ActivationDetails *info, char ***strv);
195

196
        /* This should append type-specific variables as key/value pairs for the D-Bus property of the job,
197
         * and return the number of added pairs. */
198
        int (*append_pair)(ActivationDetails *info, char ***strv);
199
} ActivationDetailsVTable;
200

201
extern const ActivationDetailsVTable * const activation_details_vtable[_UNIT_TYPE_MAX];
202

203
static inline const ActivationDetailsVTable* ACTIVATION_DETAILS_VTABLE(const ActivationDetails *a) {
50✔
204
        assert(a);
50✔
205
        assert(a->trigger_unit_type < _UNIT_TYPE_MAX);
50✔
206

207
        return activation_details_vtable[a->trigger_unit_type];
50✔
208
}
209

210
/* Newer LLVM versions don't like implicit casts from large pointer types to smaller enums, hence let's add
211
 * explicit type-safe helpers for that. */
212
static inline UnitDependency UNIT_DEPENDENCY_FROM_PTR(const void *p) {
4,260,941✔
213
        return PTR_TO_INT(p);
4,260,941✔
214
}
215

216
static inline void* UNIT_DEPENDENCY_TO_PTR(UnitDependency d) {
6,632,327✔
217
        return INT_TO_PTR(d);
6,632,327✔
218
}
219

220
struct UnitRef {
221
        /* Keeps tracks of references to a unit. This is useful so
222
         * that we can merge two units if necessary and correct all
223
         * references to them */
224

225
        Unit *source, *target;
226
        LIST_FIELDS(UnitRef, refs_by_target);
227
};
228

229
/* The generic, dynamic definition of the unit */
230
typedef struct Unit {
231
        Manager *manager;
232

233
        UnitType type;
234
        UnitLoadState load_state;
235
        Unit *merged_into;
236

237
        char *id;   /* The one special name that we use for identification */
238
        char *instance;
239

240
        Set *aliases; /* All the other names. */
241

242
        /* For each dependency type we can look up another Hashmap with this, whose key is a Unit* object,
243
         * and whose value encodes why the dependency exists, using the UnitDependencyInfo type. i.e. a
244
         * Hashmap(UnitDependency → Hashmap(Unit* → UnitDependencyInfo)) */
245
        Hashmap *dependencies;
246

247
        /* Similar, for RequiresMountsFor= and WantsMountsFor= path dependencies. The key is the path, the
248
         * value the UnitDependencyInfo type */
249
        Hashmap *mounts_for[_UNIT_MOUNT_DEPENDENCY_TYPE_MAX];
250

251
        char *description;
252
        char **documentation;
253

254
        /* The SELinux context used for checking access to this unit read off the unit file at load time (do
255
         * not confuse with the selinux_context field in ExecContext which is the SELinux context we'll set
256
         * for processes) */
257
        char *access_selinux_context;
258

259
        char *fragment_path; /* if loaded from a config file this is the primary path to it */
260
        char *source_path; /* if converted, the source file */
261
        char **dropin_paths;
262

263
        usec_t fragment_not_found_timestamp_hash;
264
        usec_t fragment_mtime;
265
        usec_t source_mtime;
266
        usec_t dropin_mtime;
267

268
        /* If this is a transient unit we are currently writing, this is where we are writing it to */
269
        FILE *transient_file;
270

271
        /* Freezer state */
272
        sd_bus_message *pending_freezer_invocation;
273
        FreezerState freezer_state;
274

275
        /* Job timeout and action to take */
276
        EmergencyAction job_timeout_action;
277
        usec_t job_timeout;
278
        usec_t job_running_timeout;
279
        char *job_timeout_reboot_arg;
280

281
        /* If there is something to do with this unit, then this is the installed job for it */
282
        Job *job;
283

284
        /* JOB_NOP jobs are special and can be installed without disturbing the real job. */
285
        Job *nop_job;
286

287
        /* The slot used for watching NameOwnerChanged signals */
288
        sd_bus_slot *match_bus_slot;
289
        sd_bus_slot *get_name_owner_slot;
290

291
        /* References to this unit from clients */
292
        sd_bus_track *bus_track;
293
        char **deserialized_refs;
294

295
        /* References to this */
296
        LIST_HEAD(UnitRef, refs_by_target);
297

298
        /* Conditions to check */
299
        LIST_HEAD(Condition, conditions);
300
        LIST_HEAD(Condition, asserts);
301

302
        dual_timestamp condition_timestamp;
303
        dual_timestamp assert_timestamp;
304

305
        /* Updated whenever the low-level state changes */
306
        dual_timestamp state_change_timestamp;
307

308
        /* Updated whenever the (high-level) active state enters or leaves the active or inactive states */
309
        dual_timestamp inactive_exit_timestamp;
310
        dual_timestamp active_enter_timestamp;
311
        dual_timestamp active_exit_timestamp;
312
        dual_timestamp inactive_enter_timestamp;
313

314
        /* Per type list */
315
        LIST_FIELDS(Unit, units_by_type);
316

317
        /* Load queue */
318
        LIST_FIELDS(Unit, load_queue);
319

320
        /* D-Bus queue */
321
        LIST_FIELDS(Unit, dbus_queue);
322

323
        /* Cleanup queue */
324
        LIST_FIELDS(Unit, cleanup_queue);
325

326
        /* GC queue */
327
        LIST_FIELDS(Unit, gc_queue);
328

329
        /* CGroup realize members queue */
330
        LIST_FIELDS(Unit, cgroup_realize_queue);
331

332
        /* cgroup empty queue */
333
        LIST_FIELDS(Unit, cgroup_empty_queue);
334

335
        /* cgroup OOM queue */
336
        LIST_FIELDS(Unit, cgroup_oom_queue);
337

338
        /* Target dependencies queue */
339
        LIST_FIELDS(Unit, target_deps_queue);
340

341
        /* Queue of units with StopWhenUnneeded= set that shall be checked for clean-up. */
342
        LIST_FIELDS(Unit, stop_when_unneeded_queue);
343

344
        /* Queue of units that have an Uphold= dependency from some other unit, and should be checked for starting */
345
        LIST_FIELDS(Unit, start_when_upheld_queue);
346

347
        /* Queue of units that have a BindTo= dependency on some other unit, and should possibly be shut down */
348
        LIST_FIELDS(Unit, stop_when_bound_queue);
349

350
        /* Queue of units that should be checked if they can release resources now */
351
        LIST_FIELDS(Unit, release_resources_queue);
352

353
        /* PIDs we keep an eye on. Note that a unit might have many more, but these are the ones we care
354
         * enough about to process SIGCHLD for */
355
        Set *pids; /* → PidRef* */
356

357
        /* Used in SIGCHLD and sd_notify() message event invocation logic to avoid that we dispatch the same event
358
         * multiple times on the same unit. */
359
        unsigned sigchldgen;
360
        unsigned notifygen;
361

362
        /* Used during GC sweeps */
363
        unsigned gc_marker;
364

365
        /* Error code when we didn't manage to load the unit (negative) */
366
        int load_error;
367

368
        /* Put a ratelimit on unit starting */
369
        RateLimit start_ratelimit;
370
        EmergencyAction start_limit_action;
371

372
        /* The unit has been marked for reload, restart, etc. Stored as 1u << marker1 | 1u << marker2. */
373
        unsigned markers;
374

375
        /* What to do on failure or success */
376
        EmergencyAction success_action, failure_action;
377
        int success_action_exit_status, failure_action_exit_status;
378
        char *reboot_arg;
379

380
        /* Make sure we never enter endless loops with the StopWhenUnneeded=, BindsTo=, Uphold= logic */
381
        RateLimit auto_start_stop_ratelimit;
382
        sd_event_source *auto_start_stop_event_source;
383

384
        /* Reference to a specific UID/GID */
385
        uid_t ref_uid;
386
        gid_t ref_gid;
387

388
        /* Cached unit file state and preset */
389
        UnitFileState unit_file_state;
390
        PresetAction unit_file_preset;
391

392
        /* How to start OnSuccess=/OnFailure= units */
393
        JobMode on_success_job_mode;
394
        JobMode on_failure_job_mode;
395

396
        /* If the job had a specific trigger that needs to be advertised (eg: a path unit), store it. */
397
        ActivationDetails *activation_details;
398

399
        /* Tweaking the GC logic */
400
        CollectMode collect_mode;
401

402
        /* The current invocation ID */
403
        sd_id128_t invocation_id;
404
        char invocation_id_string[SD_ID128_STRING_MAX]; /* useful when logging */
405

406
        /* Garbage collect us we nobody wants or requires us anymore */
407
        bool stop_when_unneeded;
408

409
        /* Create default dependencies */
410
        bool default_dependencies;
411

412
        /* Configure so that the unit survives a system transition without stopping/starting. */
413
        bool survive_final_kill_signal;
414

415
        /* Refuse manual starting, allow starting only indirectly via dependency. */
416
        bool refuse_manual_start;
417

418
        /* Don't allow the user to stop this unit manually, allow stopping only indirectly via dependency. */
419
        bool refuse_manual_stop;
420

421
        /* Allow isolation requests */
422
        bool allow_isolate;
423

424
        /* Ignore this unit when isolating */
425
        bool ignore_on_isolate;
426

427
        /* Did the last condition check succeed? */
428
        bool condition_result;
429
        bool assert_result;
430

431
        /* Is this a transient unit? */
432
        bool transient;
433

434
        /* Is this a unit that is always running and cannot be stopped? */
435
        bool perpetual;
436

437
        /* When true logs about this unit will be at debug level regardless of other log level settings */
438
        bool debug_invocation;
439

440
        /* Booleans indicating membership of this unit in the various queues */
441
        bool in_load_queue:1;
442
        bool in_dbus_queue:1;
443
        bool in_cleanup_queue:1;
444
        bool in_gc_queue:1;
445
        bool in_cgroup_realize_queue:1;
446
        bool in_cgroup_empty_queue:1;
447
        bool in_cgroup_oom_queue:1;
448
        bool in_target_deps_queue:1;
449
        bool in_stop_when_unneeded_queue:1;
450
        bool in_start_when_upheld_queue:1;
451
        bool in_stop_when_bound_queue:1;
452
        bool in_release_resources_queue:1;
453

454
        bool sent_dbus_new_signal:1;
455

456
        bool job_running_timeout_set:1;
457

458
        bool in_audit:1;
459
        bool on_console:1;
460

461
        bool start_limit_hit:1;
462

463
        /* Did we already invoke unit_coldplug() for this unit? */
464
        bool coldplugged:1;
465

466
        /* For transient units: whether to add a bus track reference after creating the unit */
467
        bool bus_track_add:1;
468

469
        /* Remember which unit state files we created */
470
        bool exported_invocation_id:1;
471
        bool exported_log_level_max:1;
472
        bool exported_log_extra_fields:1;
473
        bool exported_log_ratelimit_interval:1;
474
        bool exported_log_ratelimit_burst:1;
475

476
        /* When writing transient unit files, stores which section we stored last. If < 0, we didn't write any yet. If
477
         * == 0 we are in the [Unit] section, if > 0 we are in the unit type-specific section. */
478
        signed int last_section_private:2;
479
} Unit;
480

481
typedef struct UnitStatusMessageFormats {
482
        const char *starting_stopping[2];
483
        const char *finished_start_job[_JOB_RESULT_MAX];
484
        const char *finished_stop_job[_JOB_RESULT_MAX];
485
        /* If this entry is present, it'll be called to provide a context-dependent format string,
486
         * or NULL to fall back to finished_{start,stop}_job; if those are NULL too, fall back to generic. */
487
        const char *(*finished_job)(Unit *u, JobType t, JobResult result);
488
} UnitStatusMessageFormats;
489

490
/* Flags used when writing drop-in files or transient unit files */
491
typedef enum UnitWriteFlags {
492
        /* Write a runtime unit file or drop-in (i.e. one below /run) */
493
        UNIT_RUNTIME                = 1 << 0,
494

495
        /* Write a persistent drop-in (i.e. one below /etc) */
496
        UNIT_PERSISTENT             = 1 << 1,
497

498
        /* Place this item in the per-unit-type private section, instead of [Unit] */
499
        UNIT_PRIVATE                = 1 << 2,
500

501
        /* Apply specifier escaping */
502
        UNIT_ESCAPE_SPECIFIERS      = 1 << 3,
503

504
        /* Escape elements of ExecStart= syntax, incl. prevention of variable expansion */
505
        UNIT_ESCAPE_EXEC_SYNTAX_ENV = 1 << 4,
506

507
        /* Escape elements of ExecStart=: syntax (no variable expansion) */
508
        UNIT_ESCAPE_EXEC_SYNTAX     = 1 << 5,
509

510
        /* Apply C escaping before writing */
511
        UNIT_ESCAPE_C               = 1 << 6,
512
} UnitWriteFlags;
513

514
/* Returns true if neither persistent, nor runtime storage is requested, i.e. this is a check invocation only */
515
static inline bool UNIT_WRITE_FLAGS_NOOP(UnitWriteFlags flags) {
3,719✔
516
        return (flags & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0;
3,719✔
517
}
518

519
#include "kill.h"
520

521
/* The static const, immutable data about a specific unit type */
522
typedef struct UnitVTable {
523
        /* How much memory does an object of this unit type need */
524
        size_t object_size;
525

526
        /* If greater than 0, the offset into the object where
527
         * ExecContext is found, if the unit type has that */
528
        size_t exec_context_offset;
529

530
        /* If greater than 0, the offset into the object where
531
         * CGroupContext is found, if the unit type has that */
532
        size_t cgroup_context_offset;
533

534
        /* If greater than 0, the offset into the object where
535
         * KillContext is found, if the unit type has that */
536
        size_t kill_context_offset;
537

538
        /* If greater than 0, the offset into the object where the pointer to ExecRuntime is found, if
539
         * the unit type has that */
540
        size_t exec_runtime_offset;
541

542
        /* If greater than 0, the offset into the object where the pointer to CGroupRuntime is found, if the
543
         * unit type has that */
544
        size_t cgroup_runtime_offset;
545

546
        /* The name of the configuration file section with the private settings of this unit */
547
        const char *private_section;
548

549
        /* Config file sections this unit type understands, separated
550
         * by NUL chars */
551
        const char *sections;
552

553
        /* This should reset all type-specific variables. This should
554
         * not allocate memory, and is called with zero-initialized
555
         * data. It should hence only initialize variables that need
556
         * to be set != 0. */
557
        void (*init)(Unit *u);
558

559
        /* This should free all type-specific variables. It should be
560
         * idempotent. */
561
        void (*done)(Unit *u);
562

563
        /* Actually load data from disk. This may fail, and should set
564
         * load_state to UNIT_LOADED, UNIT_MERGED or leave it at
565
         * UNIT_STUB if no configuration could be found. */
566
        int (*load)(Unit *u);
567

568
        /* During deserialization we only record the intended state to return to. With coldplug() we actually put the
569
         * deserialized state in effect. This is where unit_notify() should be called to start things up. Note that
570
         * this callback is invoked *before* we leave the reloading state of the manager, i.e. *before* we consider the
571
         * reloading to be complete. Thus, this callback should just restore the exact same state for any unit that was
572
         * in effect before the reload, i.e. units should not catch up with changes happened during the reload. That's
573
         * what catchup() below is for. */
574
        int (*coldplug)(Unit *u);
575

576
        /* This is called shortly after all units' coldplug() call was invoked, and *after* the manager left the
577
         * reloading state. It's supposed to catch up with state changes due to external events we missed so far (for
578
         * example because they took place while we were reloading/reexecing) */
579
        void (*catchup)(Unit *u);
580

581
        void (*dump)(Unit *u, FILE *f, const char *prefix);
582

583
        int (*start)(Unit *u);
584
        int (*stop)(Unit *u);
585
        int (*reload)(Unit *u);
586

587
        /* Clear out the various runtime/state/cache/logs/configuration data */
588
        int (*clean)(Unit *u, ExecCleanMask m);
589

590
        /* Freeze or thaw the unit. Returns > 0 to indicate that the request will be handled asynchronously; unit_frozen
591
         * or unit_thawed should be called once the operation is done. Returns 0 if done successfully, or < 0 on error. */
592
        int (*freezer_action)(Unit *u, FreezerAction a);
593
        bool (*can_freeze)(const Unit *u);
594

595
        /* Return which kind of data can be cleaned */
596
        int (*can_clean)(Unit *u, ExecCleanMask *ret);
597

598
        bool (*can_reload)(Unit *u);
599

600
        /* Add a bind/image mount into the unit namespace while it is running. */
601
        int (*live_mount)(Unit *u, const char *src, const char *dst, sd_bus_message *message, MountInNamespaceFlags flags, const MountOptions *options, sd_bus_error *error);
602
        int (*can_live_mount)(Unit *u, sd_bus_error *error);
603

604
        /* Serialize state and file descriptors that should be carried over into the new
605
         * instance after reexecution. */
606
        int (*serialize)(Unit *u, FILE *f, FDSet *fds);
607

608
        /* Restore one item from the serialization */
609
        int (*deserialize_item)(Unit *u, const char *key, const char *data, FDSet *fds);
610

611
        /* Try to match up fds with what we need for this unit */
612
        void (*distribute_fds)(Unit *u, FDSet *fds);
613

614
        /* Boils down the more complex internal state of this unit to
615
         * a simpler one that the engine can understand */
616
        UnitActiveState (*active_state)(Unit *u);
617

618
        /* Returns the substate specific to this unit type as
619
         * string. This is purely information so that we can give the
620
         * user a more fine grained explanation in which actual state a
621
         * unit is in. */
622
        const char* (*sub_state_to_string)(Unit *u);
623

624
        /* Additionally to UnitActiveState determine whether unit is to be restarted. */
625
        bool (*will_restart)(Unit *u);
626

627
        /* Return false when there is a reason to prevent this unit from being gc'ed
628
         * even though nothing references it and it isn't active in any way. */
629
        bool (*may_gc)(Unit *u);
630

631
        /* Return true when the unit is not controlled by the manager (e.g. extrinsic mounts). */
632
        bool (*is_extrinsic)(Unit *u);
633

634
        /* When the unit is not running and no job for it queued we shall release its runtime resources */
635
        void (*release_resources)(Unit *u);
636

637
        /* Invoked on every child that died */
638
        void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
639

640
        /* Reset failed state if we are in failed state */
641
        void (*reset_failed)(Unit *u);
642

643
        /* Called whenever any of the cgroups this unit watches for ran empty */
644
        void (*notify_cgroup_empty)(Unit *u);
645

646
        /* Called whenever an OOM kill event on this unit was seen */
647
        void (*notify_cgroup_oom)(Unit *u, bool managed_oom);
648

649
        /* Called whenever a process of this unit sends us a message */
650
        void (*notify_message)(Unit *u, PidRef *pidref, const struct ucred *ucred, char * const *tags, FDSet *fds);
651

652
        /* Called whenever we learn a handoff timestamp */
653
        void (*notify_handoff_timestamp)(Unit *u, const struct ucred *ucred, const dual_timestamp *ts);
654

655
        /* Called whenever we learn about a child process */
656
        void (*notify_pidref)(Unit *u, PidRef *parent_pidref, PidRef *child_pidref);
657

658
        /* Called whenever a name this Unit registered for comes or goes away. */
659
        void (*bus_name_owner_change)(Unit *u, const char *new_owner);
660

661
        /* Called for each property that is being set */
662
        int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
663

664
        /* Called after at least one property got changed to apply the necessary change */
665
        int (*bus_commit_properties)(Unit *u);
666

667
        /* Return the unit this unit is following */
668
        Unit* (*following)(Unit *u);
669

670
        /* Return the set of units that are following each other */
671
        int (*following_set)(Unit *u, Set **s);
672

673
        /* Invoked each time a unit this unit is triggering changes
674
         * state or gains/loses a job */
675
        void (*trigger_notify)(Unit *u, Unit *trigger);
676

677
        /* Called whenever CLOCK_REALTIME made a jump */
678
        void (*time_change)(Unit *u);
679

680
        /* Called whenever /etc/localtime was modified */
681
        void (*timezone_change)(Unit *u);
682

683
        /* Returns the next timeout of a unit */
684
        int (*get_timeout)(Unit *u, usec_t *timeout);
685

686
        /* Returns the start timeout of a unit */
687
        usec_t (*get_timeout_start_usec)(Unit *u);
688

689
        /* Returns the main PID if there is any defined, or NULL. */
690
        PidRef* (*main_pid)(Unit *u, bool *ret_is_alien);
691

692
        /* Returns the control PID if there is any defined, or NULL. */
693
        PidRef* (*control_pid)(Unit *u);
694

695
        /* Returns true if the unit currently needs access to the console */
696
        bool (*needs_console)(Unit *u);
697

698
        /* Returns the exit status to propagate in case of FailureAction=exit/SuccessAction=exit; usually returns the
699
         * exit code of the "main" process of the service or similar. */
700
        int (*exit_status)(Unit *u);
701

702
        /* Return a copy of the status string pointer. */
703
        const char* (*status_text)(Unit *u);
704

705
        /* Like the enumerate() callback further down, but only enumerates the perpetual units, i.e. all units that
706
         * unconditionally exist and are always active. The main reason to keep both enumeration functions separate is
707
         * philosophical: the state of perpetual units should be put in place by coldplug(), while the state of those
708
         * discovered through regular enumeration should be put in place by catchup(), see below. */
709
        void (*enumerate_perpetual)(Manager *m);
710

711
        /* This is called for each unit type and should be used to enumerate units already existing in the system
712
         * internally and load them. However, everything that is loaded here should still stay in inactive state. It is
713
         * the job of the catchup() call above to put the units into the discovered state. */
714
        void (*enumerate)(Manager *m);
715

716
        /* Type specific cleanups. */
717
        void (*shutdown)(Manager *m);
718

719
        /* If this function is set and returns false all jobs for units
720
         * of this type will immediately fail. */
721
        bool (*supported)(void);
722

723
        /* If this function is set, it's invoked first as part of starting a unit to allow start rate
724
         * limiting checks to occur before we do anything else. */
725
        int (*can_start)(Unit *u);
726

727
        /* Returns > 0 if the whole subsystem is ratelimited, and new start operations should not be started
728
         * for this unit type right now. */
729
        int (*subsystem_ratelimited)(Manager *m);
730

731
        /* The strings to print in status messages */
732
        UnitStatusMessageFormats status_message_formats;
733

734
        /* True if transient units of this type are OK */
735
        bool can_transient;
736

737
        /* True if cgroup delegation is permissible */
738
        bool can_delegate;
739

740
        /* True if the unit type triggers other units, i.e. can have a UNIT_TRIGGERS dependency */
741
        bool can_trigger;
742

743
        /* True if the unit type knows a failure state, and thus can be source of an OnFailure= dependency */
744
        bool can_fail;
745

746
        /* True if units of this type shall be startable only once and then never again */
747
        bool once_only;
748

749
        /* Do not serialize this unit when preparing for root switch */
750
        bool exclude_from_switch_root_serialization;
751

752
        /* True if queued jobs of this type should be GC'ed if no other job needs them anymore */
753
        bool gc_jobs;
754

755
        /* True if systemd-oomd can monitor and act on this unit's recursive children's cgroups  */
756
        bool can_set_managed_oom;
757

758
        /* If true, we'll notify plymouth about this unit */
759
        bool notify_plymouth;
760

761
        /* If true, we'll notify a surrounding VMM/container manager about this unit becoming available */
762
        bool notify_supervisor;
763

764
        /* The audit events to generate on start + stop (or 0 if none shall be generated) */
765
        int audit_start_message_type;
766
        int audit_stop_message_type;
767
} UnitVTable;
768

769
extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
770

771
static inline const UnitVTable* UNIT_VTABLE(const Unit *u) {
23,305,255✔
772
        return unit_vtable[u->type];
23,280,464✔
773
}
774

775
/* For casting a unit into the various unit types */
776
#define DEFINE_CAST(UPPERCASE, MixedCase)                               \
777
        static inline MixedCase* UPPERCASE(Unit *u) {                   \
778
                if (_unlikely_(!u || u->type != UNIT_##UPPERCASE))      \
779
                        return NULL;                                    \
780
                                                                        \
781
                return (MixedCase*) u;                                  \
782
        }
783

784
/* For casting the various unit types into a unit */
785
#define UNIT(u)                                         \
786
        ({                                              \
787
                typeof(u) _u_ = (u);                    \
788
                Unit *_w_ = _u_ ? &(_u_)->meta : NULL;  \
789
                _w_;                                    \
790
        })
791

792
#define UNIT_HAS_EXEC_CONTEXT(u) (UNIT_VTABLE(u)->exec_context_offset > 0)
793
#define UNIT_HAS_CGROUP_CONTEXT(u) (UNIT_VTABLE(u)->cgroup_context_offset > 0)
794
#define UNIT_HAS_KILL_CONTEXT(u) (UNIT_VTABLE(u)->kill_context_offset > 0)
795

796
Unit* unit_has_dependency(const Unit *u, UnitDependencyAtom atom, Unit *other);
797
int unit_get_dependency_array(const Unit *u, UnitDependencyAtom atom, Unit ***ret_array);
798
int unit_get_transitive_dependency_set(Unit *u, UnitDependencyAtom atom, Set **ret);
799

800
static inline Hashmap* unit_get_dependencies(Unit *u, UnitDependency d) {
67,457✔
801
        return hashmap_get(u->dependencies, UNIT_DEPENDENCY_TO_PTR(d));
67,457✔
802
}
803

804
static inline Unit* UNIT_TRIGGER(Unit *u) {
1,996✔
805
        return unit_has_dependency(u, UNIT_ATOM_TRIGGERS, NULL);
1,996✔
806
}
807

808
static inline Unit* UNIT_GET_SLICE(const Unit *u) {
4,868,832✔
809
        return unit_has_dependency(u, UNIT_ATOM_IN_SLICE, NULL);
4,868,831✔
810
}
811

812
Unit* unit_new(Manager *m, size_t size);
813
Unit* unit_free(Unit *u);
814
DEFINE_TRIVIAL_CLEANUP_FUNC(Unit *, unit_free);
488,289✔
815

816
int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret);
817
int unit_add_name(Unit *u, const char *name);
818

819
int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference, UnitDependencyMask mask);
820
int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference, UnitDependencyMask mask);
821

822
int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, bool add_reference, UnitDependencyMask mask);
823
int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, bool add_reference, UnitDependencyMask mask);
824

825
int unit_add_exec_dependencies(Unit *u, ExecContext *c);
826

827
int unit_choose_id(Unit *u, const char *name);
828
int unit_set_description(Unit *u, const char *description);
829

830
void unit_release_resources(Unit *u);
831

832
bool unit_may_gc(Unit *u);
833

834
static inline bool unit_is_extrinsic(Unit *u) {
22,107✔
835
        return u->perpetual ||
22,107✔
836
                (UNIT_VTABLE(u)->is_extrinsic && UNIT_VTABLE(u)->is_extrinsic(u));
21,540✔
837
}
838

839
static inline const char* unit_status_text(Unit *u) {
403✔
840
        if (u && UNIT_VTABLE(u)->status_text)
403✔
841
                return UNIT_VTABLE(u)->status_text(u);
403✔
842
        return NULL;
843
}
844

845
void unit_add_to_load_queue(Unit *u);
846
void unit_add_to_dbus_queue(Unit *u);
847
void unit_add_to_cleanup_queue(Unit *u);
848
void unit_add_to_gc_queue(Unit *u);
849
void unit_add_to_target_deps_queue(Unit *u);
850
void unit_submit_to_stop_when_unneeded_queue(Unit *u);
851
void unit_submit_to_start_when_upheld_queue(Unit *u);
852
void unit_submit_to_stop_when_bound_queue(Unit *u);
853
void unit_submit_to_release_resources_queue(Unit *u);
854

855
int unit_merge(Unit *u, Unit *other);
856
int unit_merge_by_name(Unit *u, const char *other);
857

858
Unit *unit_follow_merge(Unit *u) _pure_;
859

860
int unit_load_fragment_and_dropin(Unit *u, bool fragment_required);
861
int unit_load(Unit *unit);
862

863
int unit_set_slice(Unit *u, Unit *slice);
864
int unit_set_default_slice(Unit *u);
865

866
const char* unit_description(Unit *u) _pure_;
867
const char* unit_status_string(Unit *u, char **combined);
868

869
bool unit_has_name(const Unit *u, const char *name);
870

871
UnitActiveState unit_active_state(Unit *u);
872

873
const char* unit_sub_state_to_string(Unit *u);
874

875
bool unit_can_reload(Unit *u) _pure_;
876
bool unit_can_start(Unit *u) _pure_;
877
bool unit_can_stop(Unit *u) _pure_;
878
bool unit_can_isolate(Unit *u) _pure_;
879

880
int unit_start(Unit *u, ActivationDetails *details);
881
int unit_stop(Unit *u);
882
int unit_reload(Unit *u);
883

884
int unit_kill(Unit *u, KillWhom w, int signo, int code, int value, sd_bus_error *ret_error);
885

886
void unit_notify_cgroup_oom(Unit *u, bool managed_oom);
887

888
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
889

890
int unit_watch_pidref(Unit *u, const PidRef *pid, bool exclusive);
891
void unit_unwatch_pidref(Unit *u, const PidRef *pid);
892
void unit_unwatch_all_pids(Unit *u);
893
void unit_unwatch_pidref_done(Unit *u, PidRef *pidref);
894

895
int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name);
896
int unit_watch_bus_name(Unit *u, const char *name);
897
void unit_unwatch_bus_name(Unit *u, const char *name);
898

899
bool unit_job_is_applicable(Unit *u, JobType j);
900

901
int setenv_unit_path(const char *p);
902

903
char* unit_dbus_path(Unit *u);
904
char* unit_dbus_path_invocation_id(Unit *u);
905

906
int unit_load_related_unit(Unit *u, const char *type, Unit **_found);
907

908
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency d, UnitDependencyMask mask);
909
int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask);
910

911
int unit_coldplug(Unit *u);
912
void unit_catchup(Unit *u);
913

914
void unit_status_printf(Unit *u, StatusType status_type, const char *status, const char *format, const char *ident) _printf_(4, 0);
915

916
bool unit_need_daemon_reload(Unit *u);
917

918
void unit_reset_failed(Unit *u);
919

920
Unit *unit_following(Unit *u);
921
int unit_following_set(Unit *u, Set **s);
922

923
const char* unit_slice_name(Unit *u);
924

925
bool unit_stop_pending(Unit *u) _pure_;
926
bool unit_inactive_or_pending(Unit *u) _pure_;
927
bool unit_active_or_pending(Unit *u);
928
bool unit_will_restart_default(Unit *u);
929
bool unit_will_restart(Unit *u);
930

931
int unit_add_default_target_dependency(Unit *u, Unit *target);
932

933
void unit_start_on_termination_deps(Unit *u, UnitDependencyAtom atom);
934
void unit_trigger_notify(Unit *u);
935

936
UnitFileState unit_get_unit_file_state(Unit *u);
937
PresetAction unit_get_unit_file_preset(Unit *u);
938

939
Unit* unit_ref_set(UnitRef *ref, Unit *source, Unit *target);
940
void unit_ref_unset(UnitRef *ref);
941

942
#define UNIT_DEREF(ref) ((ref).target)
943
#define UNIT_ISSET(ref) (!!(ref).target)
944

945
int unit_patch_contexts(Unit *u);
946

947
ExecContext* unit_get_exec_context(const Unit *u) _pure_;
948
KillContext* unit_get_kill_context(const Unit *u) _pure_;
949
CGroupContext* unit_get_cgroup_context(const Unit *u) _pure_;
950

951
ExecRuntime* unit_get_exec_runtime(const Unit *u) _pure_;
952
CGroupRuntime* unit_get_cgroup_runtime(const Unit *u) _pure_;
953

954
int unit_setup_exec_runtime(Unit *u);
955
CGroupRuntime* unit_setup_cgroup_runtime(Unit *u);
956

957
const char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf);
958
char* unit_concat_strv(char **l, UnitWriteFlags flags);
959

960
int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data);
961
int unit_write_settingf(Unit *u, UnitWriteFlags mode, const char *name, const char *format, ...) _printf_(4,5);
962

963
int unit_kill_context(Unit *u, KillOperation k);
964

965
int unit_make_transient(Unit *u);
966

967
int unit_add_mounts_for(Unit *u, const char *path, UnitDependencyMask mask, UnitMountDependencyType type);
968

969
bool unit_type_supported(UnitType t);
970

971
bool unit_is_pristine(Unit *u);
972

973
bool unit_is_unneeded(Unit *u);
974
bool unit_is_upheld_by_active(Unit *u, Unit **ret_culprit);
975
bool unit_is_bound_by_inactive(Unit *u, Unit **ret_culprit);
976

977
PidRef* unit_control_pid(Unit *u);
978
PidRef* unit_main_pid_full(Unit *u, bool *ret_is_alien);
979
static inline PidRef* unit_main_pid(Unit *u) {
7,489✔
980
        return unit_main_pid_full(u, NULL);
7,489✔
981
}
982

983
void unit_warn_if_dir_nonempty(Unit *u, const char* where);
984
int unit_log_noncanonical_mount_path(Unit *u, const char *where);
985
int unit_fail_if_noncanonical_mount_path(Unit *u, const char* where);
986

987
int unit_test_start_limit(Unit *u);
988

989
int unit_ref_uid_gid(Unit *u, uid_t uid, gid_t gid);
990
void unit_unref_uid_gid(Unit *u, bool destroy_now);
991

992
void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid);
993

994
int unit_set_invocation_id(Unit *u, sd_id128_t id);
995
int unit_acquire_invocation_id(Unit *u);
996

997
int unit_set_exec_params(Unit *s, ExecParameters *p);
998

999
int unit_fork_helper_process(Unit *u, const char *name, bool into_cgroup, PidRef *ret);
1000
int unit_fork_and_watch_rm_rf(Unit *u, char **paths, PidRef *ret);
1001

1002
void unit_remove_dependencies(Unit *u, UnitDependencyMask mask);
1003

1004
void unit_export_state_files(Unit *u);
1005
void unit_unlink_state_files(Unit *u);
1006

1007
int unit_set_debug_invocation(Unit *u, bool enable);
1008

1009
int unit_prepare_exec(Unit *u);
1010

1011
int unit_warn_leftover_processes(Unit *u, bool start);
1012

1013
bool unit_needs_console(Unit *u);
1014

1015
int unit_pid_attachable(Unit *unit, PidRef *pid, sd_bus_error *error);
1016

1017
static inline bool unit_has_job_type(Unit *u, JobType type) {
4,412✔
1018
        return u && u->job && u->job->type == type;
4,410✔
1019
}
1020

1021
static inline int unit_get_log_level_max(const Unit *u) {
298,138✔
1022
        if (u) {
298,138✔
1023
                if (u->debug_invocation)
298,137✔
1024
                        return LOG_DEBUG;
1025

1026
                ExecContext *ec = unit_get_exec_context(u);
298,137✔
1027
                if (ec && ec->log_level_max >= 0)
298,137✔
1028
                        return ec->log_level_max;
1029
        }
1030

1031
        return log_get_max_level();
298,138✔
1032
}
1033

1034
static inline bool unit_log_level_test(const Unit *u, int level) {
40,608✔
1035
        assert(u);
40,608✔
1036
        return LOG_PRI(level) <= unit_get_log_level_max(u);
40,608✔
1037
}
1038

1039
/* unit_log_skip is for cases like ExecCondition= where a unit is considered "done"
1040
 * after some execution, rather than succeeded or failed. */
1041
void unit_log_skip(Unit *u, const char *result);
1042
void unit_log_success(Unit *u);
1043
void unit_log_failure(Unit *u, const char *result);
1044
static inline void unit_log_result(Unit *u, bool success, const char *result) {
1,854✔
1045
        if (success)
1,854✔
1046
                unit_log_success(u);
1,854✔
1047
        else
1048
                unit_log_failure(u, result);
×
1049
}
1,854✔
1050

1051
void unit_log_process_exit(Unit *u, const char *kind, const char *command, bool success, int code, int status);
1052

1053
int unit_exit_status(Unit *u);
1054
int unit_success_action_exit_status(Unit *u);
1055
int unit_failure_action_exit_status(Unit *u);
1056

1057
int unit_test_trigger_loaded(Unit *u);
1058

1059
void unit_destroy_runtime_data(Unit *u, const ExecContext *context, bool destroy_runtime_dir);
1060
int unit_clean(Unit *u, ExecCleanMask mask);
1061
int unit_can_clean(Unit *u, ExecCleanMask *ret_mask);
1062

1063
bool unit_can_start_refuse_manual(Unit *u);
1064
bool unit_can_stop_refuse_manual(Unit *u);
1065
bool unit_can_isolate_refuse_manual(Unit *u);
1066

1067
bool unit_can_freeze(const Unit *u);
1068
int unit_freezer_action(Unit *u, FreezerAction action);
1069
void unit_next_freezer_state(Unit *u, FreezerAction action, FreezerState *ret_next, FreezerState *ret_objective);
1070
void unit_set_freezer_state(Unit *u, FreezerState state);
1071
void unit_freezer_complete(Unit *u, FreezerState kernel_state);
1072

1073
int unit_can_live_mount(Unit *u, sd_bus_error *error);
1074
int unit_live_mount(Unit *u, const char *src, const char *dst, sd_bus_message *message, MountInNamespaceFlags flags, const MountOptions *options, sd_bus_error *error);
1075

1076
Condition *unit_find_failed_condition(Unit *u);
1077

1078
int unit_arm_timer(Unit *u, sd_event_source **source, bool relative, usec_t usec, sd_event_time_handler_t handler);
1079

1080
bool unit_passes_filter(Unit *u, char * const *states, char * const *patterns);
1081

1082
int unit_compare_priority(Unit *a, Unit *b);
1083

1084
const char* unit_log_field(const Unit *u);
1085
const char* unit_invocation_log_field(const Unit *u);
1086

1087
UnitMountDependencyType unit_mount_dependency_type_from_string(const char *s) _const_;
1088
const char* unit_mount_dependency_type_to_string(UnitMountDependencyType t) _const_;
1089
UnitDependency unit_mount_dependency_type_to_dependency_type(UnitMountDependencyType t) _pure_;
1090

1091
const char* oom_policy_to_string(OOMPolicy i) _const_;
1092
OOMPolicy oom_policy_from_string(const char *s) _pure_;
1093

1094
/* Macros which append UNIT= or USER_UNIT= to the message */
1095

1096
#define log_unit_full_errno_zerook(unit, level, error, ...)             \
1097
        ({                                                              \
1098
                const Unit *_u = (unit);                                \
1099
                const int _l = (level);                                 \
1100
                LOG_CONTEXT_SET_LOG_LEVEL(unit_get_log_level_max(_u));  \
1101
                const ExecContext *_c = _u ? unit_get_exec_context(_u) : NULL; \
1102
                LOG_CONTEXT_PUSH_IOV(_c ? _c->log_extra_fields : NULL,  \
1103
                                     _c ? _c->n_log_extra_fields : 0);  \
1104
                _u ? log_object_internal(_l, error, PROJECT_FILE, __LINE__, __func__,  unit_log_field(_u), _u->id, unit_invocation_log_field(_u), _u->invocation_id_string, ##__VA_ARGS__) : \
1105
                     log_internal(_l, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
1106
        })
1107

1108
#define log_unit_full_errno(unit, level, error, ...) \
1109
        ({                                                              \
1110
                int _error = (error);                                   \
1111
                ASSERT_NON_ZERO(_error);                                \
1112
                log_unit_full_errno_zerook(unit, level, _error, ##__VA_ARGS__); \
1113
        })
1114

1115
#define log_unit_full(unit, level, ...) (void) log_unit_full_errno_zerook(unit, level, 0, __VA_ARGS__)
1116

1117
#define log_unit_debug(unit, ...)   log_unit_full(unit, LOG_DEBUG, __VA_ARGS__)
1118
#define log_unit_info(unit, ...)    log_unit_full(unit, LOG_INFO, __VA_ARGS__)
1119
#define log_unit_notice(unit, ...)  log_unit_full(unit, LOG_NOTICE, __VA_ARGS__)
1120
#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, __VA_ARGS__)
1121
#define log_unit_error(unit, ...)   log_unit_full(unit, LOG_ERR, __VA_ARGS__)
1122

1123
#define log_unit_debug_errno(unit, error, ...)   log_unit_full_errno(unit, LOG_DEBUG, error, __VA_ARGS__)
1124
#define log_unit_info_errno(unit, error, ...)    log_unit_full_errno(unit, LOG_INFO, error, __VA_ARGS__)
1125
#define log_unit_notice_errno(unit, error, ...)  log_unit_full_errno(unit, LOG_NOTICE, error, __VA_ARGS__)
1126
#define log_unit_warning_errno(unit, error, ...) log_unit_full_errno(unit, LOG_WARNING, error, __VA_ARGS__)
1127
#define log_unit_error_errno(unit, error, ...)   log_unit_full_errno(unit, LOG_ERR, error, __VA_ARGS__)
1128

1129
#if LOG_TRACE
1130
#  define log_unit_trace(...)          log_unit_debug(__VA_ARGS__)
1131
#  define log_unit_trace_errno(...)    log_unit_debug_errno(__VA_ARGS__)
1132
#else
1133
#  define log_unit_trace(...)          do {} while (0)
1134
#  define log_unit_trace_errno(e, ...) (-ERRNO_VALUE(e))
1135
#endif
1136

1137
#define log_unit_struct_errno(unit, level, error, ...)                  \
1138
        ({                                                              \
1139
                const Unit *_u = (unit);                                \
1140
                const int _l = (level);                                 \
1141
                LOG_CONTEXT_SET_LOG_LEVEL(unit_get_log_level_max(_u));  \
1142
                const ExecContext *_c = _u ? unit_get_exec_context(_u) : NULL; \
1143
                LOG_CONTEXT_PUSH_IOV(_c ? _c->log_extra_fields : NULL,  \
1144
                                     _c ? _c->n_log_extra_fields : 0);  \
1145
                log_struct_errno(_l, error, __VA_ARGS__, LOG_UNIT_ID(_u)); \
1146
        })
1147

1148
#define log_unit_struct(unit, level, ...) log_unit_struct_errno(unit, level, 0, __VA_ARGS__)
1149

1150
#define log_unit_struct_iovec_errno(unit, level, error, iovec, n_iovec) \
1151
        ({                                                              \
1152
                const Unit *_u = (unit);                                \
1153
                const int _l = (level);                                 \
1154
                LOG_CONTEXT_SET_LOG_LEVEL(unit_get_log_level_max(_u));  \
1155
                const ExecContext *_c = _u ? unit_get_exec_context(_u) : NULL; \
1156
                LOG_CONTEXT_PUSH_IOV(_c ? _c->log_extra_fields : NULL,  \
1157
                                     _c ? _c->n_log_extra_fields : 0);  \
1158
                log_struct_iovec_errno(_l, error, iovec, n_iovec);      \
1159
        })
1160

1161
#define log_unit_struct_iovec(unit, level, iovec, n_iovec) log_unit_struct_iovec_errno(unit, level, 0, iovec, n_iovec)
1162

1163
/* Like LOG_MESSAGE(), but with the unit name prefixed. */
1164
#define LOG_UNIT_MESSAGE(unit, fmt, ...) LOG_MESSAGE("%s: " fmt, (unit)->id, ##__VA_ARGS__)
1165
#define LOG_UNIT_ID(unit) LOG_ITEM("%s%s", unit_log_field((unit)), (unit)->id)
1166
#define LOG_UNIT_INVOCATION_ID(unit) LOG_ITEM("%s%s", unit_invocation_log_field((unit)), (unit)->invocation_id_string)
1167

1168
const char* collect_mode_to_string(CollectMode m) _const_;
1169
CollectMode collect_mode_from_string(const char *s) _pure_;
1170

1171
typedef struct UnitForEachDependencyData {
1172
        /* Stores state for the FOREACH macro below for iterating through all deps that have any of the
1173
         * specified dependency atom bits set */
1174
        UnitDependencyAtom match_atom;
1175
        Hashmap *by_type, *by_unit;
1176
        void *current_type;
1177
        Iterator by_type_iterator, by_unit_iterator;
1178
        Unit **current_unit;
1179
} UnitForEachDependencyData;
1180

1181
/* Iterates through all dependencies that have a specific atom in the dependency type set. This tries to be
1182
 * smart: if the atom is unique, we'll directly go to right entry. Otherwise we'll iterate through the
1183
 * per-dependency type hashmap and match all dep that have the right atom set. */
1184
#define _UNIT_FOREACH_DEPENDENCY(other, u, ma, data)                    \
1185
        for (UnitForEachDependencyData data = {                         \
1186
                        .match_atom = (ma),                             \
1187
                        .by_type = (u)->dependencies,                   \
1188
                        .by_type_iterator = ITERATOR_FIRST,             \
1189
                        .current_unit = &(other),                       \
1190
                };                                                      \
1191
             ({                                                         \
1192
                     UnitDependency _dt = _UNIT_DEPENDENCY_INVALID;     \
1193
                     bool _found;                                       \
1194
                                                                        \
1195
                     if (data.by_type && ITERATOR_IS_FIRST(data.by_type_iterator)) { \
1196
                             _dt = unit_dependency_from_unique_atom(data.match_atom); \
1197
                             if (_dt >= 0) {                            \
1198
                                     data.by_unit = hashmap_get(data.by_type, UNIT_DEPENDENCY_TO_PTR(_dt)); \
1199
                                     data.current_type = UNIT_DEPENDENCY_TO_PTR(_dt); \
1200
                                     data.by_type = NULL;               \
1201
                                     _found = !!data.by_unit;           \
1202
                             }                                          \
1203
                     }                                                  \
1204
                     if (_dt < 0)                                       \
1205
                             _found = hashmap_iterate(data.by_type,     \
1206
                                                      &data.by_type_iterator, \
1207
                                                      (void**)&(data.by_unit), \
1208
                                                      (const void**) &(data.current_type)); \
1209
                     _found;                                            \
1210
             }); )                                                      \
1211
                if ((unit_dependency_to_atom(UNIT_DEPENDENCY_FROM_PTR(data.current_type)) & data.match_atom) != 0) \
1212
                        for (data.by_unit_iterator = ITERATOR_FIRST;    \
1213
                                hashmap_iterate(data.by_unit,           \
1214
                                                &data.by_unit_iterator, \
1215
                                                NULL,                   \
1216
                                                (const void**) data.current_unit); )
1217

1218
/* Note: this matches deps that have *any* of the atoms specified in match_atom set */
1219
#define UNIT_FOREACH_DEPENDENCY(other, u, match_atom) \
1220
        _UNIT_FOREACH_DEPENDENCY(other, u, match_atom, UNIQ_T(data, UNIQ))
1221

1222
#define _LOG_CONTEXT_PUSH_UNIT(unit, u, c)                                                              \
1223
        const Unit *u = (unit);                                                                         \
1224
        const ExecContext *c = unit_get_exec_context(u);                                                \
1225
        LOG_CONTEXT_PUSH_KEY_VALUE(unit_log_field(u), u->id);                                           \
1226
        LOG_CONTEXT_PUSH_KEY_VALUE(unit_invocation_log_field(u), u->invocation_id_string);              \
1227
        LOG_CONTEXT_PUSH_IOV(c ? c->log_extra_fields : NULL, c ? c->n_log_extra_fields : 0);            \
1228
        LOG_CONTEXT_SET_LOG_LEVEL(unit_get_log_level_max(u))
1229

1230
#define LOG_CONTEXT_PUSH_UNIT(unit) \
1231
        _LOG_CONTEXT_PUSH_UNIT(unit, UNIQ_T(u, UNIQ), UNIQ_T(c, UNIQ))
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