ff479f
From 336ec08378b901b0372b726ace8b354ef22dd13d Mon Sep 17 00:00:00 2001
ff479f
From: Lennart Poettering <lennart@poettering.net>
ff479f
Date: Fri, 11 Sep 2020 19:49:33 +0200
ff479f
Subject: [PATCH] core: propagate triggered unit in more load states
ff479f
ff479f
In 4c2ef3276735ad9f7fccf33f5bdcbe7d8751e7ec we enabled propagating
ff479f
triggered unit state to the triggering unit for service units in more
ff479f
load states, so that we don't accidentally stop tracking state
ff479f
correctly.
ff479f
ff479f
Do the same for our other triggering unit states: automounts, paths, and
ff479f
timers.
ff479f
ff479f
Also, make this an assertion rather than a simple test. After all it
ff479f
should never happen that we get called for half-loaded units or units of
ff479f
the wrong type. The load routines should already have made this
ff479f
impossible.
ff479f
ff479f
(cherry picked from commit 0377cd2936ae5cac0c9d76a4b58889f121c097c4)
ff479f
ff479f
Related: #2086553
ff479f
---
ff479f
 src/core/automount.c   | 4 ++--
ff479f
 src/core/path.c        | 7 +++----
ff479f
 src/core/socket.c      | 4 ++--
ff479f
 src/core/timer.c       | 4 ++--
ff479f
 src/core/transaction.c | 2 +-
ff479f
 src/core/unit.h        | 4 ++++
ff479f
 6 files changed, 14 insertions(+), 11 deletions(-)
ff479f
ff479f
diff --git a/src/core/automount.c b/src/core/automount.c
ff479f
index f212620c8f..c1c513d4a5 100644
ff479f
--- a/src/core/automount.c
ff479f
+++ b/src/core/automount.c
ff479f
@@ -492,8 +492,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) {
ff479f
         assert(other);
ff479f
 
ff479f
         /* Filter out invocations with bogus state */
ff479f
-        if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT)
ff479f
-                return;
ff479f
+        assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
ff479f
+        assert(other->type == UNIT_MOUNT);
ff479f
 
ff479f
         /* Don't propagate state changes from the mount if we are already down */
ff479f
         if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))
ff479f
diff --git a/src/core/path.c b/src/core/path.c
ff479f
index 58f490589d..a7c2e0b7c1 100644
ff479f
--- a/src/core/path.c
ff479f
+++ b/src/core/path.c
ff479f
@@ -696,11 +696,10 @@ static void path_trigger_notify(Unit *u, Unit *other) {
ff479f
         assert(u);
ff479f
         assert(other);
ff479f
 
ff479f
-        /* Invoked whenever the unit we trigger changes state or gains
ff479f
-         * or loses a job */
ff479f
+        /* Invoked whenever the unit we trigger changes state or gains or loses a job */
ff479f
 
ff479f
-        if (other->load_state != UNIT_LOADED)
ff479f
-                return;
ff479f
+        /* Filter out invocations with bogus state */
ff479f
+        assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
ff479f
 
ff479f
         if (p->state == PATH_RUNNING &&
ff479f
             UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
ff479f
diff --git a/src/core/socket.c b/src/core/socket.c
ff479f
index 3589300e68..74c1cc70cb 100644
ff479f
--- a/src/core/socket.c
ff479f
+++ b/src/core/socket.c
ff479f
@@ -3190,8 +3190,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
ff479f
         assert(other);
ff479f
 
ff479f
         /* Filter out invocations with bogus state */
ff479f
-        if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
ff479f
-                return;
ff479f
+        assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
ff479f
+        assert(other->type == UNIT_SERVICE);
ff479f
 
ff479f
         /* Don't propagate state changes from the service if we are already down */
ff479f
         if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING))
ff479f
diff --git a/src/core/timer.c b/src/core/timer.c
ff479f
index 684180bf99..990f05fee4 100644
ff479f
--- a/src/core/timer.c
ff479f
+++ b/src/core/timer.c
ff479f
@@ -745,8 +745,8 @@ static void timer_trigger_notify(Unit *u, Unit *other) {
ff479f
         assert(u);
ff479f
         assert(other);
ff479f
 
ff479f
-        if (other->load_state != UNIT_LOADED)
ff479f
-                return;
ff479f
+        /* Filter out invocations with bogus state */
ff479f
+        assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
ff479f
 
ff479f
         /* Reenable all timers that depend on unit state */
ff479f
         LIST_FOREACH(value, v, t->values)
ff479f
diff --git a/src/core/transaction.c b/src/core/transaction.c
ff479f
index ee5b39fef4..8196aba927 100644
ff479f
--- a/src/core/transaction.c
ff479f
+++ b/src/core/transaction.c
ff479f
@@ -915,7 +915,7 @@ int transaction_add_job_and_dependencies(
ff479f
 
ff479f
         /* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set
ff479f
          * temporarily. */
ff479f
-        if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED))
ff479f
+        if (!UNIT_IS_LOAD_COMPLETE(unit->load_state))
ff479f
                 return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
ff479f
 
ff479f
         if (type != JOB_STOP) {
ff479f
diff --git a/src/core/unit.h b/src/core/unit.h
ff479f
index 0cd259411f..b8b914711f 100644
ff479f
--- a/src/core/unit.h
ff479f
+++ b/src/core/unit.h
ff479f
@@ -47,6 +47,10 @@ static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) {
ff479f
         return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED);
ff479f
 }
ff479f
 
ff479f
+static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) {
ff479f
+        return t >= 0 && t < _UNIT_LOAD_STATE_MAX && t != UNIT_STUB && t != UNIT_MERGED;
ff479f
+}
ff479f
+
ff479f
 /* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We
ff479f
  * use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be
ff479f
  * created as a result of multiple "reasons", hence the bitmask. */