}
}
+ // If we are a soft dependency of another target, break the acquisition from that target now:
+ if (! will_restart) {
+ for (auto dependency : soft_dpts) {
+ if (dependency->holding_acq) {
+ dependency->holding_acq = false;
+ release();
+ }
+ }
+ }
+
if (will_restart) {
// Desired state is "started".
service_set->addToStartQueue(this);
for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
ServiceRecord * to = i->getTo();
- to->release();
+ if (i->holding_acq) {
+ to->release();
+ i->holding_acq = false;
+ }
}
service_set->service_inactive(this);
if (desired_state == ServiceState::STARTED && service_state != ServiceState::STOPPED) return;
- if (required_by == 0) {
- // It really doesn't make any sense to start if there is no dependent or explicit activation.
- return;
- }
-
desired_state = ServiceState::STARTED;
service_set->addToStartQueue(this);
}
for (auto i = soft_deps.begin(); i != soft_deps.end(); ++i) {
ServiceRecord * to = i->getTo();
to->require();
+ i->holding_acq = true;
}
prop_require = false;
for (auto i = soft_dpts.begin(); i != soft_dpts.end(); i++) {
// We can send 'start', because this is only a soft dependency.
// Our startup failure means that they don't have to wait for us.
- (*i)->getFrom()->dependencyStarted();
+ if ((*i)->waiting_on) {
+ (*i)->holding_acq = false;
+ (*i)->waiting_on = false;
+ (*i)->getFrom()->dependencyStarted();
+ release();
+ }
}
}
public:
/* Whether the 'from' service is waiting for the 'to' service to start */
bool waiting_on;
+ /* Whether the 'from' service is holding an acquire on the 'to' service */
+ bool holding_acq;
- ServiceDep(ServiceRecord * from, ServiceRecord * to) noexcept : from(from), to(to), waiting_on(false)
+ ServiceDep(ServiceRecord * from, ServiceRecord * to) noexcept : from(from), to(to), waiting_on(false), holding_acq(false)
{ }
ServiceRecord * getFrom() noexcept