-/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
free(j);
}
-JobDependency* job_dependency_new(Job *subject, Job *object, bool matters) {
+JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
JobDependency *l;
assert(object);
l->subject = subject;
l->object = object;
l->matters = matters;
+ l->conflicts = conflicts;
if (subject)
LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
free(l);
}
-void job_dependency_delete(Job *subject, Job *object, bool *matters) {
- JobDependency *l;
-
- assert(object);
-
- LIST_FOREACH(object, l, object->object_list) {
- assert(l->object == object);
-
- if (l->subject == subject)
- break;
- }
-
- if (!l) {
- if (matters)
- *matters = false;
- return;
- }
-
- if (matters)
- *matters = l->matters;
-
- job_dependency_free(l);
-}
-
void job_dump(Job *j, FILE*f, const char *prefix) {
assert(j);
assert(f);
case JOB_STOP:
return
b == UNIT_INACTIVE ||
- b == UNIT_MAINTENANCE;
+ b == UNIT_FAILED;
case JOB_VERIFY_ACTIVE:
return
int job_run_and_invalidate(Job *j) {
int r;
+ uint32_t id;
+ Manager *m;
assert(j);
assert(j->installed);
j->state = JOB_RUNNING;
job_add_to_dbus_queue(j);
+ /* While we execute this operation the job might go away (for
+ * example: because it is replaced by a new, conflicting
+ * job.) To make sure we don't access a freed job later on we
+ * store the id here, so that we can verify the job is still
+ * valid. */
+ id = j->id;
+ m = j->manager;
+
switch (j->type) {
case JOB_START:
r = unit_start(j->unit);
+
+ /* If this unit cannot be started, then simply
+ * wait */
if (r == -EBADR)
r = 0;
break;
case JOB_STOP:
r = unit_stop(j->unit);
+
+ /* If this unit cannot stopped, then simply
+ * wait. */
+ if (r == -EBADR)
+ r = 0;
break;
case JOB_RELOAD:
case JOB_RESTART: {
UnitActiveState t = unit_active_state(j->unit);
- if (t == UNIT_INACTIVE || t == UNIT_MAINTENANCE || t == UNIT_ACTIVATING) {
+ if (t == UNIT_INACTIVE || t == UNIT_FAILED || t == UNIT_ACTIVATING) {
j->type = JOB_START;
r = unit_start(j->unit);
} else
case JOB_TRY_RESTART: {
UnitActiveState t = unit_active_state(j->unit);
- if (t == UNIT_INACTIVE || t == UNIT_MAINTENANCE || t == UNIT_DEACTIVATING)
+ if (t == UNIT_INACTIVE || t == UNIT_FAILED || t == UNIT_DEACTIVATING)
r = -ENOEXEC;
else if (t == UNIT_ACTIVATING) {
j->type = JOB_START;
assert_not_reached("Unknown job type");
}
- if (r == -EALREADY)
- r = job_finish_and_invalidate(j, true);
- else if (r == -EAGAIN) {
- j->state = JOB_WAITING;
- return -EAGAIN;
- } else if (r < 0)
- r = job_finish_and_invalidate(j, false);
+ if ((j = manager_get_job(m, id))) {
+ if (r == -EALREADY)
+ r = job_finish_and_invalidate(j, true);
+ else if (r == -EAGAIN)
+ j->state = JOB_WAITING;
+ else if (r < 0)
+ r = job_finish_and_invalidate(j, false);
+ }
return r;
}
return 0;
}
+ j->failed = !success;
+
log_debug("Job %s/%s finished, success=%s", j->unit->meta.id, job_type_to_string(j->type), yes_no(success));
- j->failed = !success;
+ if (j->failed)
+ j->manager->n_failed_jobs ++;
+
u = j->unit;
t = j->type;
job_free(j);
- if (!success)
+ if (!success && j->type == JOB_START)
unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "failed" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u));
/* Fail depending jobs on failure */
t == JOB_RELOAD_OR_START) {
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY], i)
- if (!other->meta.ignore_dependency_failure &&
- other->meta.job &&
+ if (other->meta.job &&
+ (other->meta.job->type == JOB_START ||
+ other->meta.job->type == JOB_VERIFY_ACTIVE ||
+ other->meta.job->type == JOB_RELOAD_OR_START))
+ job_finish_and_invalidate(other->meta.job, false);
+
+ SET_FOREACH(other, u->meta.dependencies[UNIT_BOUND_BY], i)
+ if (other->meta.job &&
(other->meta.job->type == JOB_START ||
other->meta.job->type == JOB_VERIFY_ACTIVE ||
other->meta.job->type == JOB_RELOAD_OR_START))
job_finish_and_invalidate(other->meta.job, false);
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
- if (!other->meta.ignore_dependency_failure &&
- other->meta.job &&
+ if (other->meta.job &&
!other->meta.job->override &&
(other->meta.job->type == JOB_START ||
other->meta.job->type == JOB_VERIFY_ACTIVE ||
} else if (t == JOB_STOP) {
- SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTS], i)
- if (!other->meta.ignore_dependency_failure &&
- other->meta.job &&
+ SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTED_BY], i)
+ if (other->meta.job &&
(other->meta.job->type == JOB_START ||
other->meta.job->type == JOB_VERIFY_ACTIVE ||
other->meta.job->type == JOB_RELOAD_OR_START))
if (other->meta.job)
job_add_to_run_queue(other->meta.job);
+ manager_check_finished(u->meta.manager);
+
return 0;
}