Skip to content

Commit

Permalink
pid1: fix collection of cycles of units which reference one another
Browse files Browse the repository at this point in the history
A .socket will reference a .service unit, by registering a UnitRef with the
.service unit. If this .service unit has the .socket unit listed in Wants or
Sockets or such, a cycle will be created. We would not free this cycle
properly, because we treated any unit with non-empty refs as uncollectable. To
solve this issue, treats refs with UnitRef in u->refs_by_target similarly to
the refs in u->dependencies, and check if the "other" unit is known to be
needed. If it is not needed, do not treat the reference from it as preventing
the unit we are looking at from being freed.

(cherry picked from commit 2641f02)

Resolves: #1718953
  • Loading branch information
keszybz authored and systemd-rhel-bot committed Jul 11, 2019
1 parent ff80bfd commit 703cc49
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
14 changes: 14 additions & 0 deletions src/core/manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,20 @@ static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
is_bad = false;
}

if (u->refs_by_target) {
const UnitRef *ref;

LIST_FOREACH(refs_by_target, ref, u->refs_by_target) {
unit_gc_sweep(ref->source, gc_marker);

if (ref->source->gc_marker == gc_marker + GC_OFFSET_GOOD)
goto good;

if (ref->source->gc_marker != gc_marker + GC_OFFSET_BAD)
is_bad = false;
}
}

if (is_bad)
goto bad;

Expand Down
9 changes: 5 additions & 4 deletions src/core/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,11 @@ bool unit_may_gc(Unit *u) {

/* Checks whether the unit is ready to be unloaded for garbage collection.
* Returns true when the unit may be collected, and false if there's some
* reason to keep it loaded. */
* reason to keep it loaded.
*
* References from other units are *not* checked here. Instead, this is done
* in unit_gc_sweep(), but using markers to properly collect dependency loops.
*/

if (u->job)
return false;
Expand All @@ -315,9 +319,6 @@ bool unit_may_gc(Unit *u) {
if (u->no_gc)
return false;

if (u->refs_by_target)
return false;

if (UNIT_VTABLE(u)->may_gc && !UNIT_VTABLE(u)->may_gc(u))
return false;

Expand Down

0 comments on commit 703cc49

Please sign in to comment.