]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
manager: prevent cleanup of triggering units before we start the handler
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 2 Mar 2022 12:09:06 +0000 (13:09 +0100)
committerLuca Boccassi <bluca@debian.org>
Thu, 10 Mar 2022 14:51:28 +0000 (14:51 +0000)
This fixes the following case:
OnFailure= would be spawned correctly, but OnSuccess= would be
spawned without the MONITOR_* metadata, because we'd "collect" the unit
that started successfully. So let's block cleanup while we have a job
running for the handler. The job cannot last infinitely, so at some point
we'll be able to collect both.

src/core/unit.c

index c9f88c81efe24accaab63aa2cc949a5233b0b481..bd11049c77a162dc81207b075c97b3a0675ded07 100644 (file)
@@ -375,6 +375,20 @@ int unit_set_description(Unit *u, const char *description) {
         return 0;
 }
 
+static bool unit_success_failure_handler_has_jobs(Unit *unit) {
+        Unit *other;
+
+        UNIT_FOREACH_DEPENDENCY(other, unit, UNIT_ATOM_ON_SUCCESS)
+                if (other->job || other->nop_job)
+                        return true;
+
+        UNIT_FOREACH_DEPENDENCY(other, unit, UNIT_ATOM_ON_FAILURE)
+                if (other->job || other->nop_job)
+                        return true;
+
+        return false;
+}
+
 bool unit_may_gc(Unit *u) {
         UnitActiveState state;
         int r;
@@ -389,10 +403,7 @@ bool unit_may_gc(Unit *u) {
          * in unit_gc_sweep(), but using markers to properly collect dependency loops.
          */
 
-        if (u->job)
-                return false;
-
-        if (u->nop_job)
+        if (u->job || u->nop_job)
                 return false;
 
         state = unit_active_state(u);
@@ -427,6 +438,10 @@ bool unit_may_gc(Unit *u) {
                 assert_not_reached();
         }
 
+        /* Check if any OnFailure= or on Success= jobs may be pending */
+        if (unit_success_failure_handler_has_jobs(u))
+                return false;
+
         if (u->cgroup_path) {
                 /* If the unit has a cgroup, then check whether there's anything in it. If so, we should stay
                  * around. Units with active processes should never be collected. */