if (uj) {
if (job_type_is_conflicting(uj->type, j->type))
- job_finish_and_invalidate(uj, JOB_CANCELED);
+ job_finish_and_invalidate(uj, JOB_CANCELED, true);
else {
/* not conflicting, i.e. mergeable */
if ((j = manager_get_job(m, id))) {
if (r == -EALREADY)
- r = job_finish_and_invalidate(j, JOB_DONE);
+ r = job_finish_and_invalidate(j, JOB_DONE, true);
else if (r == -ENOEXEC)
- r = job_finish_and_invalidate(j, JOB_SKIPPED);
+ r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
else if (r == -EAGAIN)
j->state = JOB_WAITING;
else if (r < 0)
- r = job_finish_and_invalidate(j, JOB_FAILED);
+ r = job_finish_and_invalidate(j, JOB_FAILED, true);
}
return r;
}
}
-int job_finish_and_invalidate(Job *j, JobResult result) {
+int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
Unit *u;
Unit *other;
JobType t;
Iterator i;
- bool recursed = false;
assert(j);
assert(j->installed);
job_print_status_message(u, t, result);
/* Fail depending jobs on failure */
- if (result != JOB_DONE) {
+ if (result != JOB_DONE && recursive) {
if (t == JOB_START ||
t == JOB_VERIFY_ACTIVE ||
if (other->job &&
(other->job->type == JOB_START ||
other->job->type == JOB_VERIFY_ACTIVE ||
- other->job->type == JOB_RELOAD_OR_START)) {
- job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
- recursed = true;
- }
+ other->job->type == JOB_RELOAD_OR_START))
+ job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
if (other->job &&
(other->job->type == JOB_START ||
other->job->type == JOB_VERIFY_ACTIVE ||
- other->job->type == JOB_RELOAD_OR_START)) {
- job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
- recursed = true;
- }
+ other->job->type == JOB_RELOAD_OR_START))
+ job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
if (other->job &&
!other->job->override &&
(other->job->type == JOB_START ||
other->job->type == JOB_VERIFY_ACTIVE ||
- other->job->type == JOB_RELOAD_OR_START)) {
- job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
- recursed = true;
- }
+ other->job->type == JOB_RELOAD_OR_START))
+ job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
} else if (t == JOB_STOP) {
if (other->job &&
(other->job->type == JOB_START ||
other->job->type == JOB_VERIFY_ACTIVE ||
- other->job->type == JOB_RELOAD_OR_START)) {
- job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
- recursed = true;
- }
+ other->job->type == JOB_RELOAD_OR_START))
+ job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
}
}
manager_check_finished(u->manager);
- return recursed;
+ return 0;
}
int job_start_timer(Job *j) {
assert(w == &j->timer_watch);
log_warning("Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
- job_finish_and_invalidate(j, JOB_TIMEOUT);
+ job_finish_and_invalidate(j, JOB_TIMEOUT, true);
}
int job_serialize(Job *j, FILE *f, FDSet *fds) {
/* When isolating first kill all installed jobs which
* aren't part of the new transaction */
- rescan:
HASHMAP_FOREACH(j, m->jobs, i) {
assert(j->installed);
if (hashmap_get(tr->jobs, j->unit))
continue;
- /* 'j' itself is safe to remove, but if other jobs
- are invalidated recursively, our iterator may become
- invalid and we need to start over. */
- if (job_finish_and_invalidate(j, JOB_CANCELED) > 0)
- goto rescan;
+ /* Not invalidating recursively. Avoids triggering
+ * OnFailure= actions of dependent jobs. Also avoids
+ * invalidating our iterator. */
+ job_finish_and_invalidate(j, JOB_CANCELED, false);
}
}
case JOB_VERIFY_ACTIVE:
if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
- job_finish_and_invalidate(u->job, JOB_DONE);
+ job_finish_and_invalidate(u->job, JOB_DONE, true);
else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
unexpected = true;
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE);
+ job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
}
break;
if (u->job->state == JOB_RUNNING) {
if (ns == UNIT_ACTIVE)
- job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED);
+ job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true);
else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) {
unexpected = true;
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE);
+ job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
}
}
case JOB_TRY_RESTART:
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, JOB_DONE);
+ job_finish_and_invalidate(u->job, JOB_DONE, true);
else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
unexpected = true;
- job_finish_and_invalidate(u->job, JOB_FAILED);
+ job_finish_and_invalidate(u->job, JOB_FAILED, true);
}
break;