job.c revision 2cba2e03524ec0922ddc70f933e8a89b7d23b4ec
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering This file is part of systemd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Copyright 2010 Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (at your option) any later version.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is distributed in the hope that it will be useful, but
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Lesser General Public License for more details.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* used for deserialization */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* We don't link it here, that's what job_dependency() is for */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(run_queue, j->manager->run_queue, j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(j->timer_event_source);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Detach from next 'bigger' objects */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* daemon-reload should be transparent to job observers */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic bool job_type_allows_late_merge(JobType t) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Tells whether it is OK to merge a job of type 't' with an already
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * running job.
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * Reloads cannot be merged this way. Think of the sequence:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * 1. Reload of a daemon is in progress; the daemon has already loaded
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * its config file, but hasn't completed the reload operation yet.
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * 2. Edit foo's config file.
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * 3. Trigger another reload to have the daemon use the new config.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Should the second reload job be merged into the first one, the daemon
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * would not know about the new config.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * JOB_RESTART jobs on the other hand can be merged, because they get
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * patched into JOB_START after stopping the unit. So if we see a
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * JOB_RESTART running, it means the unit hasn't stopped yet and at
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * this time the merge is still allowed. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void job_merge_into_installed(Job *j, Job *other) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_type_merge_and_collapse(&j->type, other->type, j->unit);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->override = j->override || other->override;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->irreversible = j->irreversible || other->irreversible;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->ignore_order = j->ignore_order || other->ignore_order;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_finish_and_invalidate(uj, JOB_CANCELED, false);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* not conflicting, i.e. mergeable */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack "Merged into installed job %s/%s as %u",
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* already running and not safe to merge into */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* Patch uj to become a merged job and re-run it. */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* XXX It should be safer to queue j to run after uj finishes, but it is
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * not currently possible to have more than one installed job per unit. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "Merged into running job, re-running: %s/%s as %u",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Install the job */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "Installed new job %s/%s as %u",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "Unit %s already has a job installed. Not installing deserialized job.",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "Reinstalled deserialized job %s/%s as %u",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart PoetteringJobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Adds a new job link, which encodes that the 'subject' job
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * needs the 'object' job in some way. If 'subject' is NULL
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * this means the 'anchor' job (i.e. the one the user
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * explicitly asked for) is the requester. */
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering LIST_PREPEND(subject, subject->subject_list, l);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_PREPEND(object, object->object_list, l);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid job_dependency_free(JobDependency *l) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(subject, l->subject->subject_list, l);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(object, l->object->object_list, l);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid job_dump(Job *j, FILE*f, const char *prefix) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s-> Job %u:\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s\tAction: %s -> %s\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s\tState: %s\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s\tForced: %s\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s\tIrreversible: %s\n",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering prefix, j->unit->id, job_type_to_string(j->type),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Merging is commutative, so imagine the matrix as symmetric. We store only
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * its lower triangle to avoid duplication. We don't store the main diagonal,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * because A merged with A is simply A.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * If the resulting type is collapsed immediately afterwards (to get rid of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * the following properties hold:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Merging is associative! A merged with B merged with C is the same as
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * A merged with C merged with B.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Mergeability is transitive! If A can be merged with B and B with C then
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * A also with C.
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * Also, if A merged with B cannot be merged with C, then either A or B cannot
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * be merged with C either.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic const JobType job_merging_table[] = {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*********************************************************************************/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart PoetteringJobType job_type_lookup_merge(JobType a, JobType b) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return job_merging_table[(a - 1) * a / 2 + b];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringbool job_type_is_redundant(JobType a, UnitActiveState b) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringvoid job_type_collapse(JobType *t, Unit *u) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering JobType t = job_type_lookup_merge(*a, b);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Checks whether there is any job running for the units this
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * job needs to be running after (in the case of a 'positive'
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * job type) or before (in the case of a 'negative' job
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Note that unit types have a say in what is runnable,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * too. For example, if they return -EAGAIN from
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * unit_start() they can indicate they are not
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * runnable yet. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* First check if there is an override */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Immediate result is that the job is or might be
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * started. In this case lets wait for the
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * dependencies, regardless whether they are
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * starting or stopping something. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Also, if something else is being stopped and we should
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * change state after it, then lets wait. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* This means that for a service a and a service b where b
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * shall be started after a:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * start a + start b → 1st step start a, 2nd step start b
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * start a + stop b → 1st step stop b, 2nd step start a
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * stop a + start b → 1st step stop a, 2nd step start b
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * stop a + stop b → 1st step stop b, 2nd step stop a
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * This has the side effect that restarts are properly
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * synchronized too. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic void job_change_type(Job *j, JobType newtype) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "Converting job %s/%s -> %s/%s",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->unit->id, job_type_to_string(j->type),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->unit->id, job_type_to_string(newtype));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering LIST_REMOVE(run_queue, j->manager->run_queue, j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* While we execute this operation the job might go away (for
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * example: because it is replaced by a new, conflicting
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * job.) To make sure we don't access a freed job later on we
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * store the id here, so that we can verify the job is still
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* If this unit cannot be started, then simply wait */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering UnitActiveState t = unit_active_state(j->unit);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* If this unit cannot stopped, then simply wait. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = job_finish_and_invalidate(j, JOB_DONE, true);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (r == -EBADR)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (r == -ENOEXEC)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = job_finish_and_invalidate(j, JOB_INVALID, true);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack else if (r == -EAGAIN) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = job_finish_and_invalidate(j, JOB_FAILED, true);
ff975efb2e88dcd5221a2f0d76c4c87e85b821a8Lennart Poettering_pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering const UnitStatusMessageFormats *format_table;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering format_table = &UNIT_VTABLE(u)->status_message_formats;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return format_table->finished_start_job[result];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (t == JOB_STOP || t == JOB_RESTART)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return format_table->finished_stop_job[result];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering_pure_ static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering format = job_get_status_message_format(u, t, result);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Return generic strings */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return "Started %s.";
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return "Failed to start %s.";
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return "Dependency failed for %s.";
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return "Timed out starting %s.";
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering } else if (t == JOB_STOP || t == JOB_RESTART) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return "Stopped %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Stopped (with error) %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Timed out stoppping %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (t == JOB_RELOAD) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Reloaded %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Reload failed for %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Timed out reloading %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#pragma GCC diagnostic ignored "-Wformat-nonliteral"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void job_print_status_message(Unit *u, JobType t, JobResult result) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering format = job_get_status_message_format(u, t, result);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering manager_status_printf(u->manager, false, NULL, "See 'systemctl status %s' for details.", u->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (t == JOB_STOP || t == JOB_RESTART) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering format = job_get_status_message_format(u, t, result);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (t == JOB_VERIFY_ACTIVE) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* When verify-active detects the unit is inactive, report it.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Most likely a DEPEND warning from a requisiting unit will
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * occur next and it's nice to see what was requisited. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#pragma GCC diagnostic ignored "-Wformat-nonliteral"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void job_log_status_message(Unit *u, JobType t, JobResult result) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Skip this if it goes to the console. since we already print
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * to the console anyway... */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering format = job_get_status_message_format_try_harder(u, t, result);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering snprintf(buf, sizeof(buf), format, unit_description(u));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "RESULT=%s", job_result_to_string(result),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (t == JOB_STOP)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "RESULT=%s", job_result_to_string(result),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "RESULT=%s", job_result_to_string(result),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug_unit(u->id, "Job %s/%s finished, result=%s",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->id, job_type_to_string(t), job_result_to_string(result));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Patch restart jobs so that they become normal start jobs */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (result == JOB_DONE && t == JOB_RESTART) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (result == JOB_FAILED || result == JOB_INVALID)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Fail depending jobs on failure */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering } else if (t == JOB_STOP) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Trigger OnFailure dependencies that are not generated by
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * the unit itself. We don't treat JOB_CANCELED as failure in
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * this context. And JOB_FAILURE is already handled by the
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * unit itself. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "JOB_RESULT=%s", job_result_to_string(result),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "Job %s/%s failed with result '%s'.",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Try to start the next jobs that can be started */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_warning_unit(j->unit->id, "Job %s/%s timed out.",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->unit->id, job_type_to_string(j->type));
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering job_finish_and_invalidate(j, JOB_TIMEOUT, true);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = sd_event_add_monotonic(j->manager->event, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j, &j->timer_event_source);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event_source_set_enabled(j->manager->run_queue_event_source, SD_EVENT_ONESHOT);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_PREPEND(run_queue, j->manager->run_queue, j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* We don't check if anybody is subscribed here, since this
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * job might just have been created and not yet assigned to a
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering LIST_PREPEND(dbus_queue, j->manager->dbus_job_queue, j);
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack if (asprintf(&p, "/org/freedesktop/systemd1/job/%"PRIu32, j->id) < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint job_serialize(Job *j, FILE *f, FDSet *fds) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-override=%s\n", yes_no(j->override));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bus_client_track_serialize(j->manager, f, j->subscribed);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* End marker */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint job_deserialize(Job *j, FILE *f, FDSet *fds) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* End marker */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (l[0] == 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (l[k] == '=') {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("Failed to parse job id value %s", v);
JobType t;
t = job_type_from_string(v);
else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
j->type = t;
JobState s;
s = job_state_from_string(v);
j->state = s;
b = parse_boolean(v);
b = parse_boolean(v);
b = parse_boolean(v);
b = parse_boolean(v);
unsigned long long ull;
assert(j);
if (j->begin_usec <= 0)
if (j->timer_event_source)
r = sd_event_add_monotonic(j->manager->event, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j, &j->timer_event_source);
assert(j);
assert(u);
if (j->timer_event_source) {