diff --git a/src/core/manager.c b/src/core/manager.c index a0c404dc9d..f90cc12910 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1350,7 +1350,9 @@ static void manager_coldplug(Manager *m) { assert(m); - /* Then, let's set up their initial state. */ + log_debug("Invoking unit coldplug() handlers…"); + + /* Let's place the units back into their deserialized state */ HASHMAP_FOREACH_KEY(u, k, m->units, i) { /* ignore aliases */ @@ -1363,6 +1365,26 @@ static void manager_coldplug(Manager *m) { } } +static void manager_catchup(Manager *m) { + Iterator i; + Unit *u; + char *k; + + assert(m); + + log_debug("Invoking unit catchup() handlers…"); + + /* Let's catch up on any state changes that happened while we were reloading/reexecing */ + HASHMAP_FOREACH_KEY(u, k, m->units, i) { + + /* ignore aliases */ + if (u->id != k) + continue; + + unit_catchup(u); + } +} + static void manager_build_unit_path_cache(Manager *m) { char **i; int r; @@ -1602,6 +1624,9 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { m->send_reloading_done = true; } + /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ + manager_catchup(m); + return 0; } @@ -3414,6 +3439,9 @@ int manager_reload(Manager *m) { manager_recheck_journal(m); manager_recheck_dbus(m); + /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ + manager_catchup(m); + /* Sync current state of bus names with our set of listening units */ q = manager_enqueue_sync_bus_names(m); if (q < 0 && r >= 0) diff --git a/src/core/unit.c b/src/core/unit.c index 7265f95c95..a82e5fd9eb 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2298,7 +2298,6 @@ static void unit_update_on_console(Unit *u) { manager_ref_console(u->manager); else manager_unref_console(u->manager); - } void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags) { @@ -3730,8 +3729,7 @@ int unit_coldplug(Unit *u) { assert(u); - /* Make sure we don't enter a loop, when coldplugging - * recursively. */ + /* Make sure we don't enter a loop, when coldplugging recursively. */ if (u->coldplugged) return 0; @@ -3759,6 +3757,13 @@ int unit_coldplug(Unit *u) { return r; } +void unit_catchup(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->catchup) + UNIT_VTABLE(u)->catchup(u); +} + static bool fragment_mtime_newer(const char *path, usec_t mtime, bool path_masked) { struct stat st; diff --git a/src/core/unit.h b/src/core/unit.h index 32bdd10643..9d9d94dd4e 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -437,10 +437,14 @@ typedef struct UnitVTable { * UNIT_STUB if no configuration could be found. */ int (*load)(Unit *u); - /* If a lot of units got created via enumerate(), this is - * where to actually set the state and call unit_notify(). */ + /* During deserialization we only record the intended state to return to. With coldplug() we actually put the + * deserialized state in effect. This is where unit_notify() should be called to start things up. */ int (*coldplug)(Unit *u); + /* This is called shortly after all units' coldplug() call was invoked. It's supposed to catch up state changes + * we missed so far (for example because they took place while we were reloading/reexecing) */ + void (*catchup)(Unit *u); + void (*dump)(Unit *u, FILE *f, const char *prefix); int (*start)(Unit *u); @@ -531,11 +535,9 @@ typedef struct UnitVTable { /* Returns true if the unit currently needs access to the console */ bool (*needs_console)(Unit *u); - /* This is called for each unit type and should be used to - * enumerate existing devices and load them. However, - * everything that is loaded here should still stay in - * inactive state. It is the job of the coldplug() call above - * to put the units into the initial state. */ + /* This is called for each unit type and should be used to enumerate units already existing in the system + * internally and load them. However, everything that is loaded here should still stay in inactive state. It is + * the job of the coldplug() call above to put the units into the initial state. */ void (*enumerate)(Manager *m); /* Type specific cleanups. */ @@ -687,6 +689,7 @@ void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *v int unit_add_node_dependency(Unit *u, const char *what, bool wants, UnitDependency d, UnitDependencyMask mask); int unit_coldplug(Unit *u); +void unit_catchup(Unit *u); void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_(3, 0); void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t);