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

systemd / systemd / 25238955322

01 May 2026 10:09AM UTC coverage: 71.943% (-0.2%) from 72.134%
25238955322

push

github

bluca
po: Translated using Weblate (Greek)

Currently translated at 100.0% (266 of 266 strings)

Co-authored-by: Jim Spentzos <jimspentzos2000@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/el/
Translation: systemd/main

324741 of 451384 relevant lines covered (71.94%)

1387736.3 hits per line

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

63.24
/src/core/scope.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <unistd.h>
4

5
#include "sd-bus.h"
6

7
#include "cgroup-setup.h"
8
#include "dbus-scope.h"
9
#include "dbus-unit.h"
10
#include "exit-status.h"
11
#include "log.h"
12
#include "manager.h"
13
#include "parse-util.h"
14
#include "pidref.h"
15
#include "random-util.h"
16
#include "scope.h"
17
#include "serialize.h"
18
#include "set.h"
19
#include "special.h"
20
#include "string-table.h"
21
#include "string-util.h"
22
#include "strv.h"
23
#include "unit.h"
24
#include "user-util.h"
25

26
static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
27
        [SCOPE_DEAD]         = UNIT_INACTIVE,
28
        [SCOPE_START_CHOWN]  = UNIT_ACTIVATING,
29
        [SCOPE_RUNNING]      = UNIT_ACTIVE,
30
        [SCOPE_ABANDONED]    = UNIT_ACTIVE,
31
        [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
32
        [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
33
        [SCOPE_FAILED]       = UNIT_FAILED,
34
};
35

36
static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
37

38
static void scope_init(Unit *u) {
742✔
39
        Scope *s = ASSERT_PTR(SCOPE(u));
742✔
40

41
        assert(u->load_state == UNIT_STUB);
742✔
42

43
        s->runtime_max_usec = USEC_INFINITY;
742✔
44
        s->timeout_stop_usec = u->manager->defaults.timeout_stop_usec;
742✔
45
        u->ignore_on_isolate = true;
742✔
46
        s->user = s->group = NULL;
742✔
47
        s->oom_policy = _OOM_POLICY_INVALID;
742✔
48
}
742✔
49

50
static void scope_done(Unit *u) {
742✔
51
        Scope *s = ASSERT_PTR(SCOPE(u));
1,484✔
52

53
        s->controller = mfree(s->controller);
742✔
54
        s->controller_track = sd_bus_track_unref(s->controller_track);
742✔
55

56
        s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
742✔
57

58
        s->user = mfree(s->user);
742✔
59
        s->group = mfree(s->group);
742✔
60
}
742✔
61

62
static usec_t scope_running_timeout(Scope *s) {
533✔
63
        usec_t delta = 0;
533✔
64

65
        assert(s);
533✔
66

67
        if (s->runtime_rand_extra_usec != 0) {
533✔
68
                delta = random_u64_range(s->runtime_rand_extra_usec);
×
69
                log_unit_debug(UNIT(s), "Adding delta of %s sec to timeout", FORMAT_TIMESPAN(delta, USEC_PER_SEC));
×
70
        }
71

72
        return usec_add(usec_add(UNIT(s)->active_enter_timestamp.monotonic,
533✔
73
                                 s->runtime_max_usec),
74
                        delta);
75
}
76

77
static int scope_arm_timer(Scope *s, bool relative, usec_t usec) {
533✔
78
        assert(s);
533✔
79

80
        return unit_arm_timer(UNIT(s), &s->timer_event_source, relative, usec, scope_dispatch_timer);
533✔
81
}
82

83
static void scope_set_state(Scope *s, ScopeState state) {
742✔
84
        ScopeState old_state;
742✔
85

86
        assert(s);
742✔
87

88
        if (s->state != state)
742✔
89
                bus_unit_send_pending_change_signal(UNIT(s), false);
742✔
90

91
        old_state = s->state;
742✔
92
        s->state = state;
742✔
93

94
        if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL, SCOPE_START_CHOWN, SCOPE_RUNNING))
742✔
95
                s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
209✔
96

97
        if (!IN_SET(old_state, SCOPE_DEAD, SCOPE_FAILED) && IN_SET(state, SCOPE_DEAD, SCOPE_FAILED))
742✔
98
                unit_unwatch_all_pids(UNIT(s));
114✔
99

100
        if (state != old_state)
742✔
101
                log_unit_debug(UNIT(s), "Changed %s -> %s",
742✔
102
                               scope_state_to_string(old_state), scope_state_to_string(state));
103

104
        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], /* reload_success= */ true);
742✔
105
}
742✔
106

107
static int scope_add_default_dependencies(Scope *s) {
536✔
108
        int r;
536✔
109

110
        assert(s);
536✔
111

112
        if (!UNIT(s)->default_dependencies)
536✔
113
                return 0;
114

115
        /* Make sure scopes are unloaded on shutdown */
116
        r = unit_add_two_dependencies_by_name(
372✔
117
                        UNIT(s),
186✔
118
                        UNIT_BEFORE, UNIT_CONFLICTS,
119
                        SPECIAL_SHUTDOWN_TARGET, true,
120
                        UNIT_DEPENDENCY_DEFAULT);
121
        if (r < 0)
186✔
122
                return r;
×
123

124
        return 0;
125
}
126

127
static int scope_verify(Scope *s) {
536✔
128
        assert(s);
536✔
129
        assert(UNIT(s)->load_state == UNIT_LOADED);
536✔
130

131
        if (set_isempty(UNIT(s)->pids) &&
536✔
132
            !MANAGER_IS_RELOADING(UNIT(s)->manager) &&
656✔
133
            !unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE))
244✔
134
                return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT), "Scope has no PIDs. Refusing.");
×
135

136
        return 0;
137
}
138

139
static int scope_load_init_scope(Unit *u) {
536✔
140
        assert(u);
536✔
141

142
        if (!unit_has_name(u, SPECIAL_INIT_SCOPE))
536✔
143
                return 0;
144

145
        u->transient = true;
350✔
146
        u->perpetual = true;
350✔
147

148
        /* init.scope is a bit special, as it has to stick around forever. Because of its special semantics we
149
         * synthesize it here, instead of relying on the unit file on disk. */
150

151
        u->default_dependencies = false;
350✔
152

153
        /* Prettify things, if we can. */
154
        if (!u->description)
350✔
155
                u->description = strdup("System and Service Manager");
350✔
156
        if (!u->documentation)
350✔
157
                (void) strv_extend(&u->documentation, "man:systemd(1)");
350✔
158

159
        return 1;
160
}
161

162
static int scope_add_extras(Scope *s) {
536✔
163
        int r;
536✔
164

165
        r = unit_patch_contexts(UNIT(s));
536✔
166
        if (r < 0)
536✔
167
                return r;
168

169
        r = unit_set_default_slice(UNIT(s));
536✔
170
        if (r < 0)
536✔
171
                return r;
172

173
        if (s->oom_policy < 0)
536✔
174
                s->oom_policy = s->cgroup_context.delegate ? OOM_CONTINUE : UNIT(s)->manager->defaults.oom_policy;
366✔
175

176
        s->cgroup_context.memory_oom_group = s->oom_policy == OOM_KILL;
536✔
177

178
        return scope_add_default_dependencies(s);
536✔
179
}
180

181
static int scope_load(Unit *u) {
866✔
182
        Scope *s = ASSERT_PTR(SCOPE(u));
866✔
183
        int r;
866✔
184

185
        assert(u->load_state == UNIT_STUB);
866✔
186

187
        if (!u->transient && !MANAGER_IS_RELOADING(u->manager))
866✔
188
                /* Refuse to load non-transient scope units, but allow them while reloading. */
189
                return -ENOENT;
190

191
        r = scope_load_init_scope(u);
536✔
192
        if (r < 0)
536✔
193
                return r;
194

195
        r = unit_load_fragment_and_dropin(u, false);
536✔
196
        if (r < 0)
536✔
197
                return r;
198

199
        if (u->load_state != UNIT_LOADED)
536✔
200
                return 0;
201

202
        r = scope_add_extras(s);
536✔
203
        if (r < 0)
536✔
204
                return r;
205

206
        return scope_verify(s);
536✔
207
}
208

209
static usec_t scope_coldplug_timeout(Scope *s) {
411✔
210
        assert(s);
411✔
211

212
        switch (s->deserialized_state) {
411✔
213

214
        case SCOPE_RUNNING:
411✔
215
                return scope_running_timeout(s);
411✔
216

217
        case SCOPE_STOP_SIGKILL:
218
        case SCOPE_STOP_SIGTERM:
219
                return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_stop_usec);
×
220

221
        default:
222
                return USEC_INFINITY;
223
        }
224
}
225

226
static int scope_coldplug(Unit *u) {
412✔
227
        Scope *s = ASSERT_PTR(SCOPE(u));
412✔
228
        int r;
412✔
229

230
        assert(s->state == SCOPE_DEAD);
412✔
231

232
        if (s->deserialized_state == s->state)
412✔
233
                return 0;
234

235
        r = scope_arm_timer(s, /* relative= */ false, scope_coldplug_timeout(s));
411✔
236
        if (r < 0)
411✔
237
                return r;
238

239
        bus_scope_track_controller(s);
411✔
240

241
        scope_set_state(s, s->deserialized_state);
411✔
242
        return 0;
411✔
243
}
244

245
static void scope_dump(Unit *u, FILE *f, const char *prefix) {
7✔
246
        Scope *s = ASSERT_PTR(SCOPE(u));
7✔
247

248
        assert(f);
7✔
249
        assert(prefix);
7✔
250

251
        fprintf(f,
14✔
252
                "%sScope State: %s\n"
253
                "%sResult: %s\n"
254
                "%sRuntimeMaxSec: %s\n"
255
                "%sRuntimeRandomizedExtraSec: %s\n"
256
                "%sOOMPolicy: %s\n",
257
                prefix, scope_state_to_string(s->state),
258
                prefix, scope_result_to_string(s->result),
259
                prefix, FORMAT_TIMESPAN(s->runtime_max_usec, USEC_PER_SEC),
7✔
260
                prefix, FORMAT_TIMESPAN(s->runtime_rand_extra_usec, USEC_PER_SEC),
7✔
261
                prefix, oom_policy_to_string(s->oom_policy));
262

263
        cgroup_context_dump(u, f, prefix);
7✔
264
        kill_context_dump(&s->kill_context, f, prefix);
7✔
265
}
7✔
266

267
static void scope_enter_dead(Scope *s, ScopeResult f) {
114✔
268
        assert(s);
114✔
269

270
        if (s->result == SCOPE_SUCCESS)
114✔
271
                s->result = f;
114✔
272

273
        unit_log_result(UNIT(s), s->result == SCOPE_SUCCESS, scope_result_to_string(s->result));
114✔
274
        scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
228✔
275
}
114✔
276

277
static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
×
278
        bool skip_signal = false;
×
279
        int r;
×
280

281
        assert(s);
×
282

283
        if (s->result == SCOPE_SUCCESS)
×
284
                s->result = f;
×
285

286
        /* If we have a controller set let's ask the controller nicely to terminate the scope, instead of us going
287
         * directly into SIGTERM berserk mode */
288
        if (state == SCOPE_STOP_SIGTERM)
×
289
                skip_signal = bus_scope_send_request_stop(s) > 0;
×
290

291
        if (skip_signal)
×
292
                r = 1; /* wait */
293
        else {
294
                r = unit_kill_context(
×
295
                                UNIT(s),
×
296
                                state != SCOPE_STOP_SIGTERM ? KILL_KILL :
297
                                s->was_abandoned            ? KILL_TERMINATE_AND_LOG :
×
298
                                                              KILL_TERMINATE);
299
                if (r < 0) {
×
300
                        log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
×
301
                        goto fail;
×
302
                }
303
        }
304

305
        if (r > 0) {
×
306
                r = scope_arm_timer(s, /* relative= */ true, s->timeout_stop_usec);
×
307
                if (r < 0) {
×
308
                        log_unit_warning_errno(UNIT(s), r, "Failed to install timer: %m");
×
309
                        goto fail;
×
310
                }
311

312
                scope_set_state(s, state);
×
313
        } else if (state == SCOPE_STOP_SIGTERM)
×
314
                scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
×
315
        else
316
                scope_enter_dead(s, SCOPE_SUCCESS);
×
317

318
        return;
319

320
fail:
×
321
        scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
×
322
}
323

324
static int scope_enter_start_chown(Scope *s) {
×
325
        Unit *u = UNIT(ASSERT_PTR(s));
×
326
        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
×
327
        int r;
×
328

329
        assert(s->user);
×
330

331
        if (!s->cgroup_runtime)
×
332
                return -EINVAL;
333

334
        r = scope_arm_timer(s, /* relative= */ true, u->manager->defaults.timeout_start_usec);
×
335
        if (r < 0)
×
336
                return r;
337

338
        r = unit_fork_helper_process(u, "(sd-chown-cgroup)", /* into_cgroup= */ true, &pidref);
×
339
        if (r < 0)
1✔
340
                goto fail;
×
341

342
        if (r == 0) {
1✔
343
                uid_t uid = UID_INVALID;
1✔
344
                gid_t gid = GID_INVALID;
1✔
345

346
                if (!isempty(s->user)) {
1✔
347
                        const char *user = s->user;
1✔
348

349
                        r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
1✔
350
                        if (r < 0) {
1✔
351
                                log_unit_error_errno(UNIT(s), r,
×
352
                                                     "Failed to resolve user '%s': %s",
353
                                                     user, STRERROR_USER(r));
354
                                _exit(EXIT_USER);
×
355
                        }
356
                }
357

358
                if (!isempty(s->group)) {
1✔
359
                        const char *group = s->group;
×
360

361
                        r = get_group_creds(&group, &gid, 0);
×
362
                        if (r < 0) {
×
363
                                log_unit_error_errno(UNIT(s), r,
×
364
                                                     "Failed to resolve group '%s': %s",
365
                                                     group, STRERROR_GROUP(r));
366
                                _exit(EXIT_GROUP);
×
367
                        }
368
                }
369

370
                r = cg_set_access(s->cgroup_runtime->cgroup_path, uid, gid);
1✔
371
                if (r < 0) {
1✔
372
                        log_unit_error_errno(UNIT(s), r, "Failed to adjust control group access: %m");
×
373
                        _exit(EXIT_CGROUP);
×
374
                }
375

376
                _exit(EXIT_SUCCESS);
1✔
377
        }
378

379
        r = unit_watch_pidref(UNIT(s), &pidref, /* exclusive= */ true);
×
380
        if (r < 0)
×
381
                goto fail;
×
382

383
        scope_set_state(s, SCOPE_START_CHOWN);
×
384

385
        return 1;
386
fail:
×
387
        s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
×
388
        return r;
×
389
}
390

391
static int scope_enter_running(Scope *s) {
122✔
392
        Unit *u = UNIT(ASSERT_PTR(s));
122✔
393
        int r;
122✔
394

395
        (void) bus_scope_track_controller(s);
122✔
396

397
        r = unit_acquire_invocation_id(u);
122✔
398
        if (r < 0)
122✔
399
                return r;
400

401
        unit_export_state_files(u);
122✔
402

403
        r = unit_attach_pids_to_cgroup(u, u->pids, NULL);
122✔
404
        if (r < 0) {
122✔
405
                log_unit_warning_errno(u, r, "Failed to add PIDs to scope's control group: %m");
×
406
                goto fail;
×
407
        }
408
        if (r == 0) {
122✔
409
                r = log_unit_warning_errno(u, SYNTHETIC_ERRNO(ECHILD), "No PIDs left to attach to the scope's control group, refusing.");
×
410
                goto fail;
×
411
        }
412
        log_unit_debug(u, "%i %s added to scope's control group.", r, r == 1 ? "process" : "processes");
122✔
413

414
        s->result = SCOPE_SUCCESS;
122✔
415

416
        scope_set_state(s, SCOPE_RUNNING);
122✔
417

418
        /* Set the maximum runtime timeout. */
419
        scope_arm_timer(s, /* relative= */ false, scope_running_timeout(s));
122✔
420

421
        /* Unwatch all pids we've just added to cgroup. We rely on empty notifications there. */
422
        unit_unwatch_all_pids(u);
122✔
423

424
        return 1;
122✔
425

426
fail:
×
427
        scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
×
428
        return r;
×
429
}
430

431
static int scope_start(Unit *u) {
122✔
432
        Scope *s = ASSERT_PTR(SCOPE(u));
122✔
433

434
        if (unit_has_name(u, SPECIAL_INIT_SCOPE))
122✔
435
                return -EPERM;
436

437
        if (s->state == SCOPE_FAILED)
122✔
438
                return -EPERM;
439

440
        /* We can't fulfill this right now, please try again later */
441
        if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
122✔
442
                return -EAGAIN;
443

444
        assert(s->state == SCOPE_DEAD);
122✔
445

446
        if (!u->transient && !MANAGER_IS_RELOADING(u->manager))
122✔
447
                return -ENOENT;
448

449
        (void) unit_realize_cgroup(u);
122✔
450
        (void) unit_reset_accounting(u);
122✔
451

452
        /* We check only for User= option to keep behavior consistent with logic for service units,
453
         * i.e. having 'Delegate=true Group=foo' w/o specifying User= has no effect. */
454
        if (s->user && unit_cgroup_delegate(u))
122✔
455
                return scope_enter_start_chown(s);
×
456

457
        return scope_enter_running(s);
122✔
458
}
459

460
static int scope_stop(Unit *u) {
×
461
        Scope *s = ASSERT_PTR(SCOPE(u));
×
462

463
        if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
×
464
                return 0;
465

466
        assert(IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED));
×
467

468
        scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
×
469
        return 1;
×
470
}
471

472
static void scope_reset_failed(Unit *u) {
2✔
473
        Scope *s = ASSERT_PTR(SCOPE(u));
2✔
474

475
        if (s->state == SCOPE_FAILED)
2✔
476
                scope_set_state(s, SCOPE_DEAD);
×
477

478
        s->result = SCOPE_SUCCESS;
2✔
479
}
2✔
480

481
static int scope_get_timeout(Unit *u, usec_t *timeout) {
×
482
        Scope *s = ASSERT_PTR(SCOPE(u));
×
483
        usec_t t;
×
484
        int r;
×
485

486
        assert(timeout);
×
487

488
        if (!s->timer_event_source)
×
489
                return 0;
×
490

491
        r = sd_event_source_get_time(s->timer_event_source, &t);
×
492
        if (r < 0)
×
493
                return r;
494
        if (t == USEC_INFINITY)
×
495
                return 0;
496

497
        *timeout = t;
×
498
        return 1;
×
499
}
500

501
static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
195✔
502
        Scope *s = ASSERT_PTR(SCOPE(u));
195✔
503
        PidRef *pid;
195✔
504

505
        assert(f);
195✔
506
        assert(fds);
195✔
507

508
        (void) serialize_item(f, "state", scope_state_to_string(s->state));
195✔
509
        (void) serialize_bool(f, "was-abandoned", s->was_abandoned);
195✔
510

511
        (void) serialize_item(f, "controller", s->controller);
195✔
512

513
        SET_FOREACH(pid, u->pids)
196✔
514
                serialize_pidref(f, fds, "pids", pid);
1✔
515

516
        return 0;
195✔
517
}
518

519
static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
338✔
520
        Scope *s = ASSERT_PTR(SCOPE(u));
338✔
521
        int r;
338✔
522

523
        assert(key);
338✔
524
        assert(value);
338✔
525
        assert(fds);
338✔
526

527
        if (streq(key, "state")) {
338✔
528
                ScopeState state;
168✔
529

530
                state = scope_state_from_string(value);
168✔
531
                if (state < 0)
168✔
532
                        log_unit_debug(u, "Failed to parse state value: %s", value);
×
533
                else
534
                        s->deserialized_state = state;
168✔
535

536
        } else if (streq(key, "was-abandoned")) {
170✔
537
                int k;
168✔
538

539
                k = parse_boolean(value);
168✔
540
                if (k < 0)
168✔
541
                        log_unit_debug(u, "Failed to parse boolean value: %s", value);
×
542
                else
543
                        s->was_abandoned = k;
168✔
544
        } else if (streq(key, "controller")) {
2✔
545

546
                r = free_and_strdup(&s->controller, value);
×
547
                if (r < 0)
×
548
                        return log_oom();
×
549

550
        } else if (streq(key, "pids")) {
2✔
551
                _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
2✔
552

553
                /* We don't check if we already received the pid before here because unit_watch_pidref()
554
                 * does this check internally and discards the new pidref if we already received it before. */
555
                if (deserialize_pidref(fds, value, &pidref) >= 0) {
2✔
556
                        r = unit_watch_pidref(u, &pidref, /* exclusive= */ false);
2✔
557
                        if (r < 0)
2✔
558
                                log_unit_debug(u, "Failed to watch PID, ignoring: %s", value);
×
559
                }
560
        } else
561
                log_unit_debug(u, "Unknown serialization key: %s", key);
×
562

563
        return 0;
564
}
565

566
static void scope_notify_cgroup_empty_event(Unit *u) {
114✔
567
        Scope *s = ASSERT_PTR(SCOPE(u));
114✔
568

569
        log_unit_debug(u, "cgroup is empty");
114✔
570

571
        if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
114✔
572
                scope_enter_dead(s, SCOPE_SUCCESS);
114✔
573
}
114✔
574

575
static void scope_notify_cgroup_oom_event(Unit *u, bool managed_oom) {
×
576
        Scope *s = ASSERT_PTR(SCOPE(u));
×
577

578
        if (managed_oom)
×
579
                log_unit_debug(u, "Process(es) of control group were killed by systemd-oomd.");
×
580
        else
581
                log_unit_debug(u, "Process of control group was killed by the OOM killer.");
×
582

583
        if (s->oom_policy == OOM_CONTINUE)
×
584
                return;
585

586
        switch (s->state) {
×
587

588
        case SCOPE_START_CHOWN:
×
589
        case SCOPE_RUNNING:
590
                scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_FAILURE_OOM_KILL);
×
591
                break;
×
592

593
        case SCOPE_STOP_SIGTERM:
×
594
                scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_OOM_KILL);
×
595
                break;
×
596

597
        case SCOPE_STOP_SIGKILL:
×
598
                if (s->result == SCOPE_SUCCESS)
×
599
                        s->result = SCOPE_FAILURE_OOM_KILL;
×
600
                break;
601
        /* SCOPE_DEAD, SCOPE_ABANDONED, and SCOPE_FAILED end up in default */
602
        default:
×
603
                ;
×
604
        }
605
}
606

607
static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
4,760✔
608
        Scope *s = ASSERT_PTR(SCOPE(u));
4,760✔
609

610
        if (s->state == SCOPE_START_CHOWN) {
4,760✔
611
                if (!is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
×
612
                        scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
×
613
                else
614
                        scope_enter_running(s);
×
615
                return;
×
616
        }
617
}
618

619
static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
×
620
        Scope *s = ASSERT_PTR(SCOPE(userdata));
×
621

622
        assert(s->timer_event_source == source);
×
623

624
        switch (s->state) {
×
625

626
        case SCOPE_RUNNING:
627
                log_unit_warning(UNIT(s), "Scope reached runtime time limit. Stopping.");
×
628
                scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_FAILURE_TIMEOUT);
×
629
                break;
×
630

631
        case SCOPE_STOP_SIGTERM:
×
632
                if (s->kill_context.send_sigkill) {
×
633
                        log_unit_warning(UNIT(s), "Stopping timed out. Killing.");
×
634
                        scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
×
635
                } else {
636
                        log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL.");
×
637
                        scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
×
638
                }
639

640
                break;
641

642
        case SCOPE_STOP_SIGKILL:
643
                log_unit_warning(UNIT(s), "Still around after SIGKILL. Ignoring.");
×
644
                scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
×
645
                break;
×
646

647
        case SCOPE_START_CHOWN:
648
                log_unit_warning(UNIT(s), "User lookup timed out. Entering failed state.");
×
649
                scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
×
650
                break;
×
651

652
        default:
×
653
                assert_not_reached();
×
654
        }
655

656
        return 0;
×
657
}
658

659
int scope_abandon(Scope *s) {
103✔
660
        assert(s);
103✔
661

662
        if (unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE))
103✔
663
                return -EPERM;
664

665
        if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
103✔
666
                return -ESTALE;
667

668
        s->was_abandoned = true;
95✔
669

670
        s->controller = mfree(s->controller);
95✔
671
        s->controller_track = sd_bus_track_unref(s->controller_track);
95✔
672

673
        scope_set_state(s, SCOPE_ABANDONED);
95✔
674

675
        return 0;
95✔
676
}
677

678
static UnitActiveState scope_active_state(Unit *u) {
27,427✔
679
        Scope *s = ASSERT_PTR(SCOPE(u));
27,427✔
680

681
        return state_translation_table[s->state];
27,427✔
682
}
683

684
static const char *scope_sub_state_to_string(Unit *u) {
681✔
685
        Scope *s = ASSERT_PTR(SCOPE(u));
681✔
686

687
        return scope_state_to_string(s->state);
681✔
688
}
689

690
static void scope_enumerate_perpetual(Manager *m) {
350✔
691
        Unit *u;
350✔
692
        int r;
350✔
693

694
        assert(m);
350✔
695

696
        /* Let's unconditionally add the "init.scope" special unit
697
         * that encapsulates PID 1. Note that PID 1 already is in the
698
         * cgroup for this, we hence just need to allocate the object
699
         * for it and that's it. */
700

701
        u = manager_get_unit(m, SPECIAL_INIT_SCOPE);
350✔
702
        if (!u) {
350✔
703
                r = unit_new_for_name(m, sizeof(Scope), SPECIAL_INIT_SCOPE, &u);
350✔
704
                if (r < 0)
350✔
705
                        return (void) log_error_errno(r, "Failed to allocate the special %s unit: %m",
×
706
                                                      SPECIAL_INIT_SCOPE);
707
        }
708

709
        u->transient = true;
350✔
710
        u->perpetual = true;
350✔
711
        SCOPE(u)->deserialized_state = SCOPE_RUNNING;
350✔
712

713
        unit_add_to_load_queue(u);
350✔
714
        unit_add_to_dbus_queue(u);
350✔
715
        /* Enqueue an explicit cgroup realization here. Unlike other cgroups this one already exists and is
716
         * populated (by us, after all!) already, even when we are not in a reload cycle. Hence we cannot
717
         * apply the settings at creation time anymore, but let's at least apply them asynchronously. */
718
        unit_add_to_cgroup_realize_queue(u);
350✔
719
}
720

721
static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
722
        [SCOPE_SUCCESS]           = "success",
723
        [SCOPE_FAILURE_RESOURCES] = "resources",
724
        [SCOPE_FAILURE_TIMEOUT]   = "timeout",
725
        [SCOPE_FAILURE_OOM_KILL]  = "oom-kill",
726
};
727

728
DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
830✔
729

730
const UnitVTable scope_vtable = {
731
        .object_size = sizeof(Scope),
732
        .cgroup_context_offset = offsetof(Scope, cgroup_context),
733
        .kill_context_offset = offsetof(Scope, kill_context),
734
        .cgroup_runtime_offset = offsetof(Scope, cgroup_runtime),
735

736
        .sections =
737
                "Unit\0"
738
                "Scope\0"
739
                "Install\0",
740
        .private_section = "Scope",
741

742
        .can_transient = true,
743
        .can_delegate = true,
744
        .can_fail = true,
745
        .once_only = true,
746
        .can_set_managed_oom = true,
747

748
        .init = scope_init,
749
        .load = scope_load,
750
        .done = scope_done,
751

752
        .coldplug = scope_coldplug,
753

754
        .dump = scope_dump,
755

756
        .start = scope_start,
757
        .stop = scope_stop,
758

759
        .freezer_action = unit_cgroup_freezer_action,
760

761
        .get_timeout = scope_get_timeout,
762

763
        .serialize = scope_serialize,
764
        .deserialize_item = scope_deserialize_item,
765

766
        .active_state = scope_active_state,
767
        .sub_state_to_string = scope_sub_state_to_string,
768

769
        .sigchld_event = scope_sigchld_event,
770

771
        .reset_failed = scope_reset_failed,
772

773
        .notify_cgroup_empty = scope_notify_cgroup_empty_event,
774
        .notify_cgroup_oom = scope_notify_cgroup_oom_event,
775

776
        .bus_set_property = bus_scope_set_property,
777
        .bus_commit_properties = bus_scope_commit_properties,
778

779
        .enumerate_perpetual = scope_enumerate_perpetual,
780
};
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