Skip to content

Commit 4918f14

Browse files
committed
core: do not drop CGroupRuntime when unit stops, but only on GC
Fixes #33149 Replaces #33145
1 parent 4c1fc52 commit 4918f14

3 files changed

Lines changed: 19 additions & 20 deletions

File tree

src/core/cgroup.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2686,7 +2686,7 @@ int unit_set_cgroup_path(Unit *u, const char *path) {
26862686
if (crt && streq_ptr(crt->cgroup_path, path))
26872687
return 0;
26882688

2689-
unit_release_cgroup(u);
2689+
unit_release_cgroup(u, /* drop_cgroup_runtime = */ true);
26902690

26912691
crt = unit_setup_cgroup_runtime(u);
26922692
if (!crt)
@@ -3484,7 +3484,7 @@ int unit_realize_cgroup(Unit *u) {
34843484
return unit_realize_cgroup_now(u, manager_state(u->manager));
34853485
}
34863486

3487-
void unit_release_cgroup(Unit *u) {
3487+
void unit_release_cgroup(Unit *u, bool drop_cgroup_runtime) {
34883488
assert(u);
34893489

34903490
/* Forgets all cgroup details for this cgroup — but does *not* destroy the cgroup. This is hence OK to call
@@ -3515,7 +3515,8 @@ void unit_release_cgroup(Unit *u) {
35153515
crt->cgroup_memory_inotify_wd = -1;
35163516
}
35173517

3518-
*(CGroupRuntime**) ((uint8_t*) u + UNIT_VTABLE(u)->cgroup_runtime_offset) = cgroup_runtime_free(crt);
3518+
if (drop_cgroup_runtime)
3519+
*(CGroupRuntime**) ((uint8_t*) u + UNIT_VTABLE(u)->cgroup_runtime_offset) = cgroup_runtime_free(crt);
35193520
}
35203521

35213522
int unit_cgroup_is_empty(Unit *u) {
@@ -3535,31 +3536,33 @@ int unit_cgroup_is_empty(Unit *u) {
35353536
return r;
35363537
}
35373538

3538-
bool unit_maybe_release_cgroup(Unit *u) {
3539+
static bool unit_maybe_release_cgroup(Unit *u) {
35393540
int r;
35403541

3541-
assert(u);
3542+
/* Releases the cgroup only if it is recursively empty.
3543+
* Returns true if the cgroup was released, false otherwise. */
35423544

3543-
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
3544-
if (!crt || !crt->cgroup_path)
3545-
return true;
3545+
assert(u);
35463546

35473547
/* Don't release the cgroup if there are still processes under it. If we get notified later when all
35483548
* the processes exit (e.g. the processes were in D-state and exited after the unit was marked as
35493549
* failed) we need the cgroup paths to continue to be tracked by the manager so they can be looked up
35503550
* and cleaned up later. */
35513551
r = unit_cgroup_is_empty(u);
35523552
if (r > 0) {
3553-
unit_release_cgroup(u);
3553+
/* Do not free CGroupRuntime when called from unit_prune_cgroup. Various accounting data
3554+
* we should keep, especially CPU usage and *_peak ones which would be shown even after
3555+
* the unit stops. */
3556+
unit_release_cgroup(u, /* drop_cgroup_runtime = */ false);
35543557
return true;
35553558
}
35563559

35573560
return false;
35583561
}
35593562

35603563
void unit_prune_cgroup(Unit *u) {
3561-
int r;
35623564
bool is_root_slice;
3565+
int r;
35633566

35643567
assert(u);
35653568

@@ -3597,9 +3600,8 @@ void unit_prune_cgroup(Unit *u) {
35973600
if (!unit_maybe_release_cgroup(u)) /* Returns true if the cgroup was released */
35983601
return;
35993602

3600-
crt = unit_get_cgroup_runtime(u); /* The above might have destroyed the runtime object, let's see if it's still there */
3601-
if (!crt)
3602-
return;
3603+
assert(crt == unit_get_cgroup_runtime(u));
3604+
assert(!crt->cgroup_path);
36033605

36043606
crt->cgroup_realized = false;
36053607
crt->cgroup_realized_mask = 0;

src/core/cgroup.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -449,10 +449,7 @@ int unit_watch_cgroup_memory(Unit *u);
449449
void unit_add_to_cgroup_realize_queue(Unit *u);
450450

451451
int unit_cgroup_is_empty(Unit *u);
452-
void unit_release_cgroup(Unit *u);
453-
/* Releases the cgroup only if it is recursively empty.
454-
* Returns true if the cgroup was released, false otherwise. */
455-
bool unit_maybe_release_cgroup(Unit *u);
452+
void unit_release_cgroup(Unit *u, bool drop_cgroup_runtime);
456453

457454
void unit_add_to_cgroup_empty_queue(Unit *u);
458455
int unit_check_oomd_kill(Unit *u);

src/core/unit.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,8 @@ bool unit_may_gc(Unit *u) {
481481
/* If the unit has a cgroup, then check whether there's anything in it. If so, we should stay
482482
* around. Units with active processes should never be collected. */
483483
r = unit_cgroup_is_empty(u);
484-
if (r <= 0 && r != -ENXIO)
485-
return false; /* ENXIO means: currently not realized */
484+
if (r <= 0 && !IN_SET(r, -ENXIO, -EOWNERDEAD))
485+
return false; /* ENXIO/EOWNERDEAD means: currently not realized */
486486

487487
if (!UNIT_VTABLE(u)->may_gc)
488488
return true;
@@ -787,7 +787,7 @@ Unit* unit_free(Unit *u) {
787787
if (u->on_console)
788788
manager_unref_console(u->manager);
789789

790-
unit_release_cgroup(u);
790+
unit_release_cgroup(u, /* drop_cgroup_runtime = */ true);
791791

792792
if (!MANAGER_IS_RELOADING(u->manager))
793793
unit_unlink_state_files(u);

0 commit comments

Comments
 (0)