diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2017-02-14 23:06:50 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-14 23:06:50 -0500 |
commit | cd8e857f88089cb5f70a17eea9883ed6c006e106 (patch) | |
tree | b6097b7075440f38989097b60bde4808b122d9fb /src | |
parent | b1d7520ab5c94f648c51991aaa603bbccc2610f5 (diff) | |
parent | 62d3ca2469328b59f533bdc955cc6738cb053176 (diff) |
Merge pull request #4733 from poettering/binds-to
When we are about to start a unit, check the deps again.
Diffstat (limited to 'src')
-rw-r--r-- | src/core/job.c | 2 | ||||
-rw-r--r-- | src/core/unit.c | 33 |
2 files changed, 35 insertions, 0 deletions
diff --git a/src/core/job.c b/src/core/job.c index 00f7d7998f..07f4b74c5c 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -627,6 +627,8 @@ int job_run_and_invalidate(Job *j) { r = job_finish_and_invalidate(j, JOB_ASSERT, true, false); else if (r == -EOPNOTSUPP) r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true, false); + else if (r == -ENOLINK) + r = job_finish_and_invalidate(j, JOB_DEPENDENCY, true, false); else if (r == -EAGAIN) job_set_state(j, JOB_WAITING); else if (r < 0) diff --git a/src/core/unit.c b/src/core/unit.c index 5e4b1567d8..0b680e9544 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1527,6 +1527,7 @@ int unit_start_limit_test(Unit *u) { } bool unit_shall_confirm_spawn(Unit *u) { + assert(u); if (manager_is_confirm_spawn_disabled(u->manager)) return false; @@ -1537,6 +1538,31 @@ bool unit_shall_confirm_spawn(Unit *u) { return !unit_get_exec_context(u)->same_pgrp; } +static bool unit_verify_deps(Unit *u) { + Unit *other; + Iterator j; + + assert(u); + + /* Checks whether all BindsTo= dependencies of this unit are fulfilled — if they are also combined with + * After=. We do not check Requires= or Requisite= here as they only should have an effect on the job + * processing, but do not have any effect afterwards. We don't check BindsTo= dependencies that are not used in + * conjunction with After= as for them any such check would make things entirely racy. */ + + SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], j) { + + if (!set_contains(u->dependencies[UNIT_AFTER], other)) + continue; + + if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(other))) { + log_unit_notice(u, "Bound to unit %s, but unit isn't active.", other->id); + return false; + } + } + + return true; +} + /* Errors: * -EBADR: This unit type does not support starting. * -EALREADY: Unit is already started. @@ -1545,6 +1571,7 @@ bool unit_shall_confirm_spawn(Unit *u) { * -EPROTO: Assert failed * -EINVAL: Unit not loaded * -EOPNOTSUPP: Unit type not supported + * -ENOLINK: The necessary dependencies are not fulfilled. */ int unit_start(Unit *u) { UnitActiveState state; @@ -1590,6 +1617,12 @@ int unit_start(Unit *u) { if (!unit_supported(u)) return -EOPNOTSUPP; + /* Let's make sure that the deps really are in order before we start this. Normally the job engine should have + * taken care of this already, but let's check this here again. After all, our dependencies might not be in + * effect anymore, due to a reload or due to a failed condition. */ + if (!unit_verify_deps(u)) + return -ENOLINK; + /* Forward to the main object, if we aren't it. */ following = unit_following(u); if (following) { |