units: fix BindsTo= logic when applied relative to services with Type=oneshot

Start jobs for Type=oneshot units are successful when the unit state
transition activating → inactive took place. In such a case all units
that BindsTo= on it previously would continue to run, even though the unit
they dependet on was actually already gone.
This commit is contained in:
Lennart Poettering 2014-08-18 22:21:42 +02:00
parent 8257df2767
commit ff50244582

View file

@ -1471,12 +1471,44 @@ static void unit_check_unneeded(Unit *u) {
if (unit_active_or_pending(other))
return;
log_info_unit(u->id, "Service %s is not needed anymore. Stopping.", u->id);
log_info_unit(u->id, "Unit %s is not needed anymore. Stopping.", u->id);
/* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL);
}
static void unit_check_binds_to(Unit *u) {
bool stop = false;
Unit *other;
Iterator i;
assert(u);
if (u->job)
return;
if (unit_active_state(u) != UNIT_ACTIVE)
return;
SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i) {
if (other->job)
continue;
if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
continue;
stop = true;
}
if (!stop)
return;
log_info_unit(u->id, "Unit %s is bound to inactive service. Stopping, too.", u->id);
/* A unit we need to run is gone. Sniff. Let's stop this. */
manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL);
}
static void retroactively_start_dependencies(Unit *u) {
Iterator i;
Unit *other;
@ -1788,11 +1820,19 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
manager_recheck_journal(m);
unit_trigger_notify(u);
/* Maybe we finished startup and are now ready for being
* stopped because unneeded? */
if (u->manager->n_reloading <= 0)
if (u->manager->n_reloading <= 0) {
/* Maybe we finished startup and are now ready for
* being stopped because unneeded? */
unit_check_unneeded(u);
/* Maybe we finished startup, but something we needed
* has vanished? Let's die then. (This happens when
* something BindsTo= to a Type=oneshot unit, as these
* units go directly from starting to inactive,
* without ever entering started.) */
unit_check_binds_to(u);
}
unit_add_to_dbus_queue(u);
unit_add_to_gc_queue(u);
}