1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/timerfd.h>
25 #include <sys/epoll.h>
27 #include "systemd/sd-id128.h"
28 #include "systemd/sd-messages.h"
33 #include "load-fragment.h"
34 #include "load-dropin.h"
41 JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
45 name_len = strlen(name);
46 cl = malloc0(sizeof(JobBusClient) + name_len + 1);
51 memcpy(cl->name, name, name_len + 1);
55 Job* job_new_raw(Unit *unit) {
58 /* used for deserialization */
66 j->manager = unit->manager;
68 j->type = _JOB_TYPE_INVALID;
69 j->timer_watch.type = WATCH_INVALID;
74 Job* job_new(Unit *unit, JobType type) {
77 assert(type < _JOB_TYPE_MAX);
79 j = job_new_raw(unit);
83 j->id = j->manager->current_job_id++;
86 /* We don't link it here, that's what job_dependency() is for */
91 void job_free(Job *j) {
95 assert(!j->installed);
96 assert(!j->transaction_prev);
97 assert(!j->transaction_next);
98 assert(!j->subject_list);
99 assert(!j->object_list);
102 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
104 if (j->in_dbus_queue)
105 LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
107 if (j->timer_watch.type != WATCH_INVALID) {
108 assert(j->timer_watch.type == WATCH_JOB_TIMER);
109 assert(j->timer_watch.data.job == j);
110 assert(j->timer_watch.fd >= 0);
112 assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
113 close_nointr_nofail(j->timer_watch.fd);
116 while ((cl = j->bus_client_list)) {
117 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
123 void job_uninstall(Job *j) {
126 assert(j->installed);
128 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
131 /* Detach from next 'bigger' objects */
133 /* daemon-reload should be transparent to job observers */
134 if (j->manager->n_reloading <= 0)
135 bus_job_send_removed_signal(j);
139 unit_add_to_gc_queue(j->unit);
141 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
142 j->installed = false;
145 static bool job_type_allows_late_merge(JobType t) {
146 /* Tells whether it is OK to merge a job of type 't' with an already
148 * Reloads cannot be merged this way. Think of the sequence:
149 * 1. Reload of a daemon is in progress; the daemon has already loaded
150 * its config file, but hasn't completed the reload operation yet.
151 * 2. Edit foo's config file.
152 * 3. Trigger another reload to have the daemon use the new config.
153 * Should the second reload job be merged into the first one, the daemon
154 * would not know about the new config.
155 * JOB_RESTART jobs on the other hand can be merged, because they get
156 * patched into JOB_START after stopping the unit. So if we see a
157 * JOB_RESTART running, it means the unit hasn't stopped yet and at
158 * this time the merge is still allowed. */
159 return t != JOB_RELOAD;
162 static void job_merge_into_installed(Job *j, Job *other) {
163 assert(j->installed);
164 assert(j->unit == other->unit);
166 if (j->type != JOB_NOP)
167 job_type_merge_and_collapse(&j->type, other->type, j->unit);
169 assert(other->type == JOB_NOP);
171 j->override = j->override || other->override;
172 j->irreversible = j->irreversible || other->irreversible;
173 j->ignore_order = j->ignore_order || other->ignore_order;
176 Job* job_install(Job *j) {
180 assert(!j->installed);
181 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
183 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
187 if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
188 job_finish_and_invalidate(uj, JOB_CANCELED, false);
190 /* not conflicting, i.e. mergeable */
192 if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
193 (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
194 job_merge_into_installed(uj, j);
195 log_debug_unit(uj->unit->id,
196 "Merged into installed job %s/%s as %u",
197 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
200 /* already running and not safe to merge into */
201 /* Patch uj to become a merged job and re-run it. */
202 /* XXX It should be safer to queue j to run after uj finishes, but it is
203 * not currently possible to have more than one installed job per unit. */
204 job_merge_into_installed(uj, j);
205 log_debug_unit(uj->unit->id,
206 "Merged into running job, re-running: %s/%s as %u",
207 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
208 uj->state = JOB_WAITING;
209 uj->manager->n_running_jobs--;
215 /* Install the job */
218 j->manager->n_installed_jobs ++;
219 log_debug_unit(j->unit->id,
220 "Installed new job %s/%s as %u",
221 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
225 int job_install_deserialized(Job *j) {
228 assert(!j->installed);
230 if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
231 log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
235 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
238 log_debug_unit(j->unit->id,
239 "Unit %s already has a job installed. Not installing deserialized job.",
245 log_debug_unit(j->unit->id,
246 "Reinstalled deserialized job %s/%s as %u",
247 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
251 JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
256 /* Adds a new job link, which encodes that the 'subject' job
257 * needs the 'object' job in some way. If 'subject' is NULL
258 * this means the 'anchor' job (i.e. the one the user
259 * explicitly asked for) is the requester. */
261 if (!(l = new0(JobDependency, 1)))
264 l->subject = subject;
266 l->matters = matters;
267 l->conflicts = conflicts;
270 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
272 LIST_PREPEND(JobDependency, object, object->object_list, l);
277 void job_dependency_free(JobDependency *l) {
281 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
283 LIST_REMOVE(JobDependency, object, l->object->object_list, l);
288 void job_dump(Job *j, FILE*f, const char *prefix) {
297 "%s\tAction: %s -> %s\n"
300 "%s\tIrreversible: %s\n",
302 prefix, j->unit->id, job_type_to_string(j->type),
303 prefix, job_state_to_string(j->state),
304 prefix, yes_no(j->override),
305 prefix, yes_no(j->irreversible));
309 * Merging is commutative, so imagine the matrix as symmetric. We store only
310 * its lower triangle to avoid duplication. We don't store the main diagonal,
311 * because A merged with A is simply A.
313 * If the resulting type is collapsed immediately afterwards (to get rid of
314 * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
315 * the following properties hold:
317 * Merging is associative! A merged with B merged with C is the same as
318 * A merged with C merged with B.
320 * Mergeability is transitive! If A can be merged with B and B with C then
323 * Also, if A merged with B cannot be merged with C, then either A or B cannot
324 * be merged with C either.
326 static const JobType job_merging_table[] = {
327 /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
328 /*********************************************************************************/
330 /*JOB_VERIFY_ACTIVE */ JOB_START,
331 /*JOB_STOP */ -1, -1,
332 /*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
333 /*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
336 JobType job_type_lookup_merge(JobType a, JobType b) {
337 assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
338 assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
339 assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
350 return job_merging_table[(a - 1) * a / 2 + b];
353 bool job_type_is_redundant(JobType a, UnitActiveState b) {
363 b == UNIT_INACTIVE ||
366 case JOB_VERIFY_ACTIVE:
377 b == UNIT_ACTIVATING;
380 assert_not_reached("Invalid job type");
384 void job_type_collapse(JobType *t, Unit *u) {
389 case JOB_TRY_RESTART:
390 s = unit_active_state(u);
391 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
397 case JOB_RELOAD_OR_START:
398 s = unit_active_state(u);
399 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
410 int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
411 JobType t = job_type_lookup_merge(*a, b);
415 job_type_collapse(a, u);
419 bool job_is_runnable(Job *j) {
424 assert(j->installed);
426 /* Checks whether there is any job running for the units this
427 * job needs to be running after (in the case of a 'positive'
428 * job type) or before (in the case of a 'negative' job
431 /* First check if there is an override */
435 if (j->type == JOB_NOP)
438 if (j->type == JOB_START ||
439 j->type == JOB_VERIFY_ACTIVE ||
440 j->type == JOB_RELOAD) {
442 /* Immediate result is that the job is or might be
443 * started. In this case lets wait for the
444 * dependencies, regardless whether they are
445 * starting or stopping something. */
447 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
452 /* Also, if something else is being stopped and we should
453 * change state after it, then lets wait. */
455 SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
457 (other->job->type == JOB_STOP ||
458 other->job->type == JOB_RESTART))
461 /* This means that for a service a and a service b where b
462 * shall be started after a:
464 * start a + start b → 1st step start a, 2nd step start b
465 * start a + stop b → 1st step stop b, 2nd step start a
466 * stop a + start b → 1st step stop a, 2nd step start b
467 * stop a + stop b → 1st step stop b, 2nd step stop a
469 * This has the side effect that restarts are properly
470 * synchronized too. */
475 static void job_change_type(Job *j, JobType newtype) {
476 log_debug_unit(j->unit->id,
477 "Converting job %s/%s -> %s/%s",
478 j->unit->id, job_type_to_string(j->type),
479 j->unit->id, job_type_to_string(newtype));
484 int job_run_and_invalidate(Job *j) {
487 Manager *m = j->manager;
490 assert(j->installed);
491 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
492 assert(j->in_run_queue);
494 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
495 j->in_run_queue = false;
497 if (j->state != JOB_WAITING)
500 if (!job_is_runnable(j))
503 j->state = JOB_RUNNING;
505 job_add_to_dbus_queue(j);
507 /* While we execute this operation the job might go away (for
508 * example: because it is replaced by a new, conflicting
509 * job.) To make sure we don't access a freed job later on we
510 * store the id here, so that we can verify the job is still
517 r = unit_start(j->unit);
519 /* If this unit cannot be started, then simply wait */
524 case JOB_VERIFY_ACTIVE: {
525 UnitActiveState t = unit_active_state(j->unit);
526 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
528 else if (t == UNIT_ACTIVATING)
537 r = unit_stop(j->unit);
539 /* If this unit cannot stopped, then simply wait. */
545 r = unit_reload(j->unit);
553 assert_not_reached("Unknown job type");
556 j = manager_get_job(m, id);
559 r = job_finish_and_invalidate(j, JOB_DONE, true);
560 else if (r == -ENOEXEC)
561 r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
562 else if (r == -EAGAIN) {
563 j->state = JOB_WAITING;
566 r = job_finish_and_invalidate(j, JOB_FAILED, true);
572 static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
573 const UnitStatusMessageFormats *format_table;
577 assert(t < _JOB_TYPE_MAX);
579 format_table = &UNIT_VTABLE(u)->status_message_formats;
584 return format_table->finished_start_job[result];
585 else if (t == JOB_STOP || t == JOB_RESTART)
586 return format_table->finished_stop_job[result];
591 static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
596 assert(t < _JOB_TYPE_MAX);
598 format = job_get_status_message_format(u, t, result);
602 /* Return generic strings */
603 if (t == JOB_START) {
604 if (result == JOB_DONE)
605 return "Started %s.";
606 else if (result == JOB_FAILED)
607 return "Failed to start %s.";
608 else if (result == JOB_DEPENDENCY)
609 return "Dependency failed for %s.";
610 else if (result == JOB_TIMEOUT)
611 return "Timed out starting %s.";
612 } else if (t == JOB_STOP || t == JOB_RESTART) {
613 if (result == JOB_DONE)
614 return "Stopped %s.";
615 else if (result == JOB_FAILED)
616 return "Stopped (with error) %s.";
617 else if (result == JOB_TIMEOUT)
618 return "Timed out stoppping %s.";
619 } else if (t == JOB_RELOAD) {
620 if (result == JOB_DONE)
621 return "Reloaded %s.";
622 else if (result == JOB_FAILED)
623 return "Reload failed for %s.";
624 else if (result == JOB_TIMEOUT)
625 return "Timed out reloading %s.";
631 static void job_print_status_message(Unit *u, JobType t, JobResult result) {
636 assert(t < _JOB_TYPE_MAX);
638 if (t == JOB_START) {
639 format = job_get_status_message_format(u, t, result);
646 if (u->condition_result)
647 unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
651 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format);
652 manager_status_printf(u->manager, false, NULL, "See 'systemctl status %s' for details.", u->id);
656 unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format);
660 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
667 } else if (t == JOB_STOP || t == JOB_RESTART) {
669 format = job_get_status_message_format(u, t, result);
676 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
681 unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
688 } else if (t == JOB_VERIFY_ACTIVE) {
690 /* When verify-active detects the unit is inactive, report it.
691 * Most likely a DEPEND warning from a requisiting unit will
692 * occur next and it's nice to see what was requisited. */
693 if (result == JOB_SKIPPED)
694 unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.");
698 #pragma GCC diagnostic push
699 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
700 static void job_log_status_message(Unit *u, JobType t, JobResult result) {
706 assert(t < _JOB_TYPE_MAX);
708 /* Skip this if it goes to the console. since we already print
709 * to the console anyway... */
711 if (log_on_console())
714 format = job_get_status_message_format_try_harder(u, t, result);
718 snprintf(buf, sizeof(buf), format, unit_description(u));
721 if (t == JOB_START) {
724 mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
725 log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
728 "RESULT=%s", job_result_to_string(result),
732 } else if (t == JOB_STOP)
733 log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
735 MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
736 "RESULT=%s", job_result_to_string(result),
740 else if (t == JOB_RELOAD)
741 log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
743 MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
744 "RESULT=%s", job_result_to_string(result),
748 #pragma GCC diagnostic pop
750 int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
757 assert(j->installed);
758 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
765 if (j->state == JOB_RUNNING)
766 j->manager->n_running_jobs--;
768 log_debug_unit(u->id, "Job %s/%s finished, result=%s",
769 u->id, job_type_to_string(t), job_result_to_string(result));
771 job_print_status_message(u, t, result);
772 job_log_status_message(u, t, result);
774 job_add_to_dbus_queue(j);
776 /* Patch restart jobs so that they become normal start jobs */
777 if (result == JOB_DONE && t == JOB_RESTART) {
779 job_change_type(j, JOB_START);
780 j->state = JOB_WAITING;
782 job_add_to_run_queue(j);
787 if (result == JOB_FAILED)
788 j->manager->n_failed_jobs ++;
793 /* Fail depending jobs on failure */
794 if (result != JOB_DONE && recursive) {
796 if (t == JOB_START ||
797 t == JOB_VERIFY_ACTIVE) {
799 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
801 (other->job->type == JOB_START ||
802 other->job->type == JOB_VERIFY_ACTIVE))
803 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
805 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
807 (other->job->type == JOB_START ||
808 other->job->type == JOB_VERIFY_ACTIVE))
809 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
811 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
813 !other->job->override &&
814 (other->job->type == JOB_START ||
815 other->job->type == JOB_VERIFY_ACTIVE))
816 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
818 } else if (t == JOB_STOP) {
820 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
822 (other->job->type == JOB_START ||
823 other->job->type == JOB_VERIFY_ACTIVE))
824 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
828 /* Trigger OnFailure dependencies that are not generated by
829 * the unit itself. We don't treat JOB_CANCELED as failure in
830 * this context. And JOB_FAILURE is already handled by the
832 if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
833 log_struct_unit(LOG_NOTICE,
835 "JOB_TYPE=%s", job_type_to_string(t),
836 "JOB_RESULT=%s", job_result_to_string(result),
837 "Job %s/%s failed with result '%s'.",
839 job_type_to_string(t),
840 job_result_to_string(result),
843 unit_trigger_on_failure(u);
847 /* Try to start the next jobs that can be started */
848 SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
850 job_add_to_run_queue(other->job);
851 SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
853 job_add_to_run_queue(other->job);
855 manager_check_finished(u->manager);
860 int job_start_timer(Job *j) {
861 struct itimerspec its = {};
862 struct epoll_event ev = {
863 .data.ptr = &j->timer_watch,
868 if (j->unit->job_timeout <= 0 ||
869 j->timer_watch.type == WATCH_JOB_TIMER)
872 assert(j->timer_watch.type == WATCH_INVALID);
874 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
879 timespec_store(&its.it_value, j->unit->job_timeout);
881 if (timerfd_settime(fd, 0, &its, NULL) < 0) {
886 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
891 j->timer_watch.type = WATCH_JOB_TIMER;
892 j->timer_watch.fd = fd;
893 j->timer_watch.data.job = j;
899 close_nointr_nofail(fd);
904 void job_add_to_run_queue(Job *j) {
906 assert(j->installed);
911 LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
912 j->in_run_queue = true;
915 void job_add_to_dbus_queue(Job *j) {
917 assert(j->installed);
919 if (j->in_dbus_queue)
922 /* We don't check if anybody is subscribed here, since this
923 * job might just have been created and not yet assigned to a
924 * connection/client. */
926 LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
927 j->in_dbus_queue = true;
930 char *job_dbus_path(Job *j) {
935 if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
941 void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
943 assert(w == &j->timer_watch);
945 log_warning_unit(j->unit->id, "Job %s/%s timed out.",
946 j->unit->id, job_type_to_string(j->type));
947 job_finish_and_invalidate(j, JOB_TIMEOUT, true);
950 int job_serialize(Job *j, FILE *f, FDSet *fds) {
951 fprintf(f, "job-id=%u\n", j->id);
952 fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
953 fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
954 fprintf(f, "job-override=%s\n", yes_no(j->override));
955 fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
956 fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
957 fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
958 /* Cannot save bus clients. Just note the fact that we're losing
959 * them. job_send_message() will fallback to broadcasting. */
960 fprintf(f, "job-forgot-bus-clients=%s\n",
961 yes_no(j->forgot_bus_clients || j->bus_client_list));
962 if (j->timer_watch.type == WATCH_JOB_TIMER) {
963 int copy = fdset_put_dup(fds, j->timer_watch.fd);
966 fprintf(f, "job-timer-watch-fd=%d\n", copy);
974 int job_deserialize(Job *j, FILE *f, FDSet *fds) {
976 char line[LINE_MAX], *l, *v;
979 if (!fgets(line, sizeof(line), f)) {
1000 if (streq(l, "job-id")) {
1001 if (safe_atou32(v, &j->id) < 0)
1002 log_debug("Failed to parse job id value %s", v);
1003 } else if (streq(l, "job-type")) {
1004 JobType t = job_type_from_string(v);
1006 log_debug("Failed to parse job type %s", v);
1007 else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
1008 log_debug("Cannot deserialize job of type %s", v);
1011 } else if (streq(l, "job-state")) {
1012 JobState s = job_state_from_string(v);
1014 log_debug("Failed to parse job state %s", v);
1017 } else if (streq(l, "job-override")) {
1018 int b = parse_boolean(v);
1020 log_debug("Failed to parse job override flag %s", v);
1022 j->override = j->override || b;
1023 } else if (streq(l, "job-irreversible")) {
1024 int b = parse_boolean(v);
1026 log_debug("Failed to parse job irreversible flag %s", v);
1028 j->irreversible = j->irreversible || b;
1029 } else if (streq(l, "job-sent-dbus-new-signal")) {
1030 int b = parse_boolean(v);
1032 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
1034 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
1035 } else if (streq(l, "job-ignore-order")) {
1036 int b = parse_boolean(v);
1038 log_debug("Failed to parse job ignore_order flag %s", v);
1040 j->ignore_order = j->ignore_order || b;
1041 } else if (streq(l, "job-forgot-bus-clients")) {
1042 int b = parse_boolean(v);
1044 log_debug("Failed to parse job forgot_bus_clients flag %s", v);
1046 j->forgot_bus_clients = j->forgot_bus_clients || b;
1047 } else if (streq(l, "job-timer-watch-fd")) {
1049 if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
1050 log_debug("Failed to parse job-timer-watch-fd value %s", v);
1052 if (j->timer_watch.type == WATCH_JOB_TIMER)
1053 close_nointr_nofail(j->timer_watch.fd);
1055 j->timer_watch.type = WATCH_JOB_TIMER;
1056 j->timer_watch.fd = fdset_remove(fds, fd);
1057 j->timer_watch.data.job = j;
1063 int job_coldplug(Job *j) {
1064 struct epoll_event ev = {
1065 .data.ptr = &j->timer_watch,
1069 if (j->timer_watch.type != WATCH_JOB_TIMER)
1072 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
1078 void job_shutdown_magic(Job *j) {
1081 /* The shutdown target gets some special treatment here: we
1082 * tell the kernel to begin with flushing its disk caches, to
1083 * optimize shutdown time a bit. Ideally we wouldn't hardcode
1084 * this magic into PID 1. However all other processes aren't
1085 * options either since they'd exit much sooner than PID 1 and
1086 * asynchronous sync() would cause their exit to be
1089 if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
1092 if (j->type != JOB_START)
1095 if (detect_container(NULL) > 0)
1098 asynchronous_sync();
1101 static const char* const job_state_table[_JOB_STATE_MAX] = {
1102 [JOB_WAITING] = "waiting",
1103 [JOB_RUNNING] = "running"
1106 DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
1108 static const char* const job_type_table[_JOB_TYPE_MAX] = {
1109 [JOB_START] = "start",
1110 [JOB_VERIFY_ACTIVE] = "verify-active",
1111 [JOB_STOP] = "stop",
1112 [JOB_RELOAD] = "reload",
1113 [JOB_RELOAD_OR_START] = "reload-or-start",
1114 [JOB_RESTART] = "restart",
1115 [JOB_TRY_RESTART] = "try-restart",
1119 DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
1121 static const char* const job_mode_table[_JOB_MODE_MAX] = {
1122 [JOB_FAIL] = "fail",
1123 [JOB_REPLACE] = "replace",
1124 [JOB_REPLACE_IRREVERSIBLY] = "replace-irreversibly",
1125 [JOB_ISOLATE] = "isolate",
1126 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
1127 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
1130 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
1132 static const char* const job_result_table[_JOB_RESULT_MAX] = {
1133 [JOB_DONE] = "done",
1134 [JOB_CANCELED] = "canceled",
1135 [JOB_TIMEOUT] = "timeout",
1136 [JOB_FAILED] = "failed",
1137 [JOB_DEPENDENCY] = "dependency",
1138 [JOB_SKIPPED] = "skipped"
1141 DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);