X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjob.c;h=1520d81ad908fb3daf9040fc45ab40e72fb55cf8;hp=53c47d4a724fe8388f4878c0fa83596a7fbf1e25;hb=ead51eb4ed55981f290e40a871ffbca6480c4cd3;hpb=5d44db4a905c62d6cf0dfabbf61df49621efec22 diff --git a/src/job.c b/src/job.c index 53c47d4a7..1520d81ad 100644 --- a/src/job.c +++ b/src/job.c @@ -101,7 +101,7 @@ JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool /* Adds a new job link, which encodes that the 'subject' job * needs the 'object' job in some way. If 'subject' is NULL * this means the 'anchor' job (i.e. the one the user - * explcitily asked for) is the requester. */ + * explicitly asked for) is the requester. */ if (!(l = new0(JobDependency, 1))) return NULL; @@ -313,7 +313,7 @@ bool job_is_runnable(Job *j) { * type. */ /* First check if there is an override */ - if (j->ignore_deps) + if (j->ignore_order) return true; if (j->type == JOB_START || @@ -422,10 +422,16 @@ int job_run_and_invalidate(Job *j) { break; case JOB_RELOAD_OR_START: - if (unit_active_state(j->unit) == UNIT_ACTIVE) + if (unit_active_state(j->unit) == UNIT_ACTIVE) { + j->type = JOB_RELOAD; r = unit_reload(j->unit); - else + } else { + j->type = JOB_START; r = unit_start(j->unit); + + if (r == -EBADR) + r = 0; + } break; case JOB_RESTART: { @@ -445,8 +451,10 @@ int job_run_and_invalidate(Job *j) { else if (t == UNIT_ACTIVATING) { j->type = JOB_START; r = unit_start(j->unit); - } else + } else { + j->type = JOB_RESTART; r = unit_stop(j->unit); + } break; } @@ -457,22 +465,70 @@ int job_run_and_invalidate(Job *j) { if ((j = manager_get_job(m, id))) { if (r == -EALREADY) r = job_finish_and_invalidate(j, JOB_DONE); + else if (r == -ENOEXEC) + r = job_finish_and_invalidate(j, JOB_SKIPPED); else if (r == -EAGAIN) j->state = JOB_WAITING; else if (r < 0) r = job_finish_and_invalidate(j, JOB_FAILED); - else - job_start_timer(j); } return r; } +static void job_print_status_message(Unit *u, JobType t, JobResult result) { + assert(u); + + if (t == JOB_START) { + + switch (result) { + + case JOB_DONE: + unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, "Started %s", unit_description(u)); + break; + + case JOB_FAILED: + unit_status_printf(u, ANSI_HIGHLIGHT_ON "FAILED" ANSI_HIGHLIGHT_OFF, "Failed to start %s", unit_description(u)); + unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->meta.id); + break; + + case JOB_DEPENDENCY: + unit_status_printf(u, ANSI_HIGHLIGHT_ON " ABORT" ANSI_HIGHLIGHT_OFF, "Dependency failed. Aborted start of %s", unit_description(u)); + break; + + case JOB_TIMEOUT: + unit_status_printf(u, ANSI_HIGHLIGHT_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out starting %s", unit_description(u)); + break; + + default: + ; + } + + } else if (t == JOB_STOP) { + + switch (result) { + + case JOB_TIMEOUT: + unit_status_printf(u, ANSI_HIGHLIGHT_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out stopping %s", unit_description(u)); + break; + + case JOB_DONE: + case JOB_FAILED: + unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, "Stopped %s", unit_description(u)); + break; + + default: + ; + } + } +} + int job_finish_and_invalidate(Job *j, JobResult result) { Unit *u; Unit *other; JobType t; Iterator i; + bool recursed = false; assert(j); assert(j->installed); @@ -490,7 +546,9 @@ int job_finish_and_invalidate(Job *j, JobResult result) { j->type = JOB_START; job_add_to_run_queue(j); - return 0; + + u = j->unit; + goto finish; } j->result = result; @@ -504,12 +562,7 @@ int job_finish_and_invalidate(Job *j, JobResult result) { t = j->type; job_free(j); - if (result == JOB_FAILED && j->type == JOB_START) - unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "failed" ANSI_HIGHLIGHT_OFF ", see 'systemctl status %s' for details.\n", unit_description(u), u->meta.id); - else if (result == JOB_TIMEOUT && j->type == JOB_START) - unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "timed out" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u), u->meta.id); - else if (result == JOB_TIMEOUT && j->type == JOB_STOP) - unit_status_printf(u, "Stopping %s " ANSI_HIGHLIGHT_ON "timed out" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u), u->meta.id); + job_print_status_message(u, t, result); /* Fail depending jobs on failure */ if (result != JOB_DONE) { @@ -522,23 +575,29 @@ int job_finish_and_invalidate(Job *j, JobResult result) { 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)) + other->meta.job->type == JOB_RELOAD_OR_START)) { job_finish_and_invalidate(other->meta.job, JOB_DEPENDENCY); + recursed = true; + } 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)) + other->meta.job->type == JOB_RELOAD_OR_START)) { job_finish_and_invalidate(other->meta.job, JOB_DEPENDENCY); + recursed = true; + } SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i) if (other->meta.job && !other->meta.job->override && (other->meta.job->type == JOB_START || other->meta.job->type == JOB_VERIFY_ACTIVE || - other->meta.job->type == JOB_RELOAD_OR_START)) + other->meta.job->type == JOB_RELOAD_OR_START)) { job_finish_and_invalidate(other->meta.job, JOB_DEPENDENCY); + recursed = true; + } } else if (t == JOB_STOP) { @@ -546,11 +605,27 @@ int job_finish_and_invalidate(Job *j, JobResult result) { 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)) + other->meta.job->type == JOB_RELOAD_OR_START)) { job_finish_and_invalidate(other->meta.job, JOB_DEPENDENCY); + recursed = true; + } } } + /* Trigger OnFailure dependencies that are not generated by + * the unit itself. We don't tread JOB_CANCELED as failure in + * this context. And JOB_FAILURE is already handled by the + * unit itself. */ + if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) { + log_notice("Job %s/%s failed with result '%s'.", + u->meta.id, + job_type_to_string(t), + job_result_to_string(result)); + + unit_trigger_on_failure(u); + } + +finish: /* Try to start the next jobs that can be started */ SET_FOREACH(other, u->meta.dependencies[UNIT_AFTER], i) if (other->meta.job) @@ -561,7 +636,7 @@ int job_finish_and_invalidate(Job *j, JobResult result) { manager_check_finished(u->meta.manager); - return 0; + return recursed; } int job_start_timer(Job *j) { @@ -679,7 +754,8 @@ static const char* const job_mode_table[_JOB_MODE_MAX] = { [JOB_FAIL] = "fail", [JOB_REPLACE] = "replace", [JOB_ISOLATE] = "isolate", - [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies" + [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies", + [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements" }; DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode); @@ -689,7 +765,8 @@ static const char* const job_result_table[_JOB_RESULT_MAX] = { [JOB_CANCELED] = "canceled", [JOB_TIMEOUT] = "timeout", [JOB_FAILED] = "failed", - [JOB_DEPENDENCY] = "dependency" + [JOB_DEPENDENCY] = "dependency", + [JOB_SKIPPED] = "skipped" }; DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);