core: explicitly verify that BindsTo= deps are in order before dispatch start operation of a unit
Let's make sure we verify that all BindsTo= are in order before we actually go and dispatch a start operation to a unit. Normally the job queue should already have made sure all deps are in order, but this might not have been sufficient in two cases: a) when the user changes deps during runtime and reloads the daemon, and b) when the user placed BindsTo= dependencies without matching After= dependencies, so that we don't actually wait for the bound to unit to be up before upping also the binding unit. See: #4725
This commit is contained in:
parent
290f0ff9aa
commit
631b676bb7
4
NEWS
4
NEWS
|
@ -35,6 +35,10 @@ CHANGES WITH 233 in spe
|
||||||
names of remote hosts and to reply to mDNS's A and AAAA requests
|
names of remote hosts and to reply to mDNS's A and AAAA requests
|
||||||
from the hosts.
|
from the hosts.
|
||||||
|
|
||||||
|
* When units are about to be started an additional check is now done to
|
||||||
|
ensure that all dependencies of type BindsTo= (when used in
|
||||||
|
combination with After=) have been started.
|
||||||
|
|
||||||
CHANGES WITH 232:
|
CHANGES WITH 232:
|
||||||
|
|
||||||
* The new RemoveIPC= option can be used to remove IPC objects owned by
|
* The new RemoveIPC= option can be used to remove IPC objects owned by
|
||||||
|
|
|
@ -627,6 +627,8 @@ int job_run_and_invalidate(Job *j) {
|
||||||
r = job_finish_and_invalidate(j, JOB_ASSERT, true, false);
|
r = job_finish_and_invalidate(j, JOB_ASSERT, true, false);
|
||||||
else if (r == -EOPNOTSUPP)
|
else if (r == -EOPNOTSUPP)
|
||||||
r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true, false);
|
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)
|
else if (r == -EAGAIN)
|
||||||
job_set_state(j, JOB_WAITING);
|
job_set_state(j, JOB_WAITING);
|
||||||
else if (r < 0)
|
else if (r < 0)
|
||||||
|
|
|
@ -1527,6 +1527,7 @@ int unit_start_limit_test(Unit *u) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool unit_shall_confirm_spawn(Unit *u) {
|
bool unit_shall_confirm_spawn(Unit *u) {
|
||||||
|
assert(u);
|
||||||
|
|
||||||
if (manager_is_confirm_spawn_disabled(u->manager))
|
if (manager_is_confirm_spawn_disabled(u->manager))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1537,6 +1538,31 @@ bool unit_shall_confirm_spawn(Unit *u) {
|
||||||
return !unit_get_exec_context(u)->same_pgrp;
|
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:
|
/* Errors:
|
||||||
* -EBADR: This unit type does not support starting.
|
* -EBADR: This unit type does not support starting.
|
||||||
* -EALREADY: Unit is already started.
|
* -EALREADY: Unit is already started.
|
||||||
|
@ -1545,6 +1571,7 @@ bool unit_shall_confirm_spawn(Unit *u) {
|
||||||
* -EPROTO: Assert failed
|
* -EPROTO: Assert failed
|
||||||
* -EINVAL: Unit not loaded
|
* -EINVAL: Unit not loaded
|
||||||
* -EOPNOTSUPP: Unit type not supported
|
* -EOPNOTSUPP: Unit type not supported
|
||||||
|
* -ENOLINK: The necessary dependencies are not fulfilled.
|
||||||
*/
|
*/
|
||||||
int unit_start(Unit *u) {
|
int unit_start(Unit *u) {
|
||||||
UnitActiveState state;
|
UnitActiveState state;
|
||||||
|
@ -1590,6 +1617,12 @@ int unit_start(Unit *u) {
|
||||||
if (!unit_supported(u))
|
if (!unit_supported(u))
|
||||||
return -EOPNOTSUPP;
|
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. */
|
/* Forward to the main object, if we aren't it. */
|
||||||
following = unit_following(u);
|
following = unit_following(u);
|
||||||
if (following) {
|
if (following) {
|
||||||
|
|
Loading…
Reference in New Issue