From f78f265f405a61387c6c12a879ac0d6b6dc958db Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Apr 2015 16:04:50 +0200 Subject: core: always coldplug units that are triggered by other units before those Let's make sure that we don't enqueue triggering jobs for units before those units are actually fully loaded. http://lists.freedesktop.org/archives/systemd-devel/2015-April/031176.html https://bugs.freedesktop.org/show_bug.cgi?id=88401 diff --git a/src/core/unit.c b/src/core/unit.c index 70a2b57..2b356e2 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2876,13 +2876,32 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) { } int unit_coldplug(Unit *u) { + Unit *other; + Iterator i; int r; assert(u); - if (UNIT_VTABLE(u)->coldplug) - if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0) + /* Make sure we don't enter a loop, when coldplugging + * recursively. */ + if (u->coldplugged) + return 0; + + u->coldplugged = true; + + /* Make sure everything that we might pull in through + * triggering is coldplugged before us */ + SET_FOREACH(other, u->dependencies[UNIT_TRIGGERS], i) { + r = unit_coldplug(other); + if (r < 0) return r; + } + + if (UNIT_VTABLE(u)->coldplug) { + r = UNIT_VTABLE(u)->coldplug(u); + if (r < 0) + return r; + } if (u->job) { r = job_coldplug(u->job); diff --git a/src/core/unit.h b/src/core/unit.h index be306a0..1a44271 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -104,6 +104,7 @@ struct Unit { char *fragment_path; /* if loaded from a config file this is the primary path to it */ char *source_path; /* if converted, the source file */ char **dropin_paths; + usec_t fragment_mtime; usec_t source_mtime; usec_t dropin_mtime; @@ -233,6 +234,9 @@ struct Unit { bool cgroup_realized:1; bool cgroup_members_mask_valid:1; bool cgroup_subtree_mask_valid:1; + + /* Did we already invoke unit_coldplug() for this unit? */ + bool coldplugged; }; struct UnitStatusMessageFormats { -- cgit v0.10.2 From 4370633083dd9453da183c468cf89cc17254ac39 Mon Sep 17 00:00:00 2001 From: Ivan Shapovalov Date: Mon, 27 Apr 2015 21:19:02 +0300 Subject: core: coldplug all units which participate in jobs during coldplugging This is yet another attempt to fix coldplugging order (more especially, the problem which happens when one creates a job during coldplugging and it references a not-yet-coldplugged unit). Now we forcibly coldplug all units which participate in jobs. This is a superset of previously implemented handling of the UNIT_TRIGGERS dependencies, so that handling is removed. http://lists.freedesktop.org/archives/systemd-devel/2015-April/031212.html https://bugs.freedesktop.org/show_bug.cgi?id=88401 (once again) diff --git a/src/core/transaction.c b/src/core/transaction.c index 5974b1e..7b19e2f 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -848,6 +848,13 @@ int transaction_add_job_and_dependencies( assert(type < _JOB_TYPE_MAX_IN_TRANSACTION); assert(unit); + /* Before adding jobs for this unit, let's ensure that its state has been loaded + * This matters when jobs are spawned as part of coldplugging itself (see e. g. path_coldplug()). + * This way, we "recursively" coldplug units, ensuring that we do not look at state of + * not-yet-coldplugged units. */ + if (unit->manager->n_reloading > 0) + unit_coldplug(unit); + /* log_debug("Pulling in %s/%s from %s/%s", */ /* unit->id, job_type_to_string(type), */ /* by ? by->unit->id : "NA", */ diff --git a/src/core/unit.c b/src/core/unit.c index 496db6c..b7ab084 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2893,14 +2893,6 @@ int unit_coldplug(Unit *u) { u->coldplugged = true; - /* Make sure everything that we might pull in through - * triggering is coldplugged before us */ - SET_FOREACH(other, u->dependencies[UNIT_TRIGGERS], i) { - r = unit_coldplug(other); - if (r < 0) - return r; - } - if (UNIT_VTABLE(u)->coldplug) { r = UNIT_VTABLE(u)->coldplug(u); if (r < 0) -- cgit v0.10.2