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"
38 JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
42 name_len = strlen(name);
43 cl = malloc0(sizeof(JobBusClient) + name_len + 1);
48 memcpy(cl->name, name, name_len + 1);
52 Job* job_new_raw(Unit *unit) {
55 /* used for deserialization */
63 j->manager = unit->manager;
65 j->type = _JOB_TYPE_INVALID;
66 j->timer_watch.type = WATCH_INVALID;
71 Job* job_new(Unit *unit, JobType type) {
74 assert(type < _JOB_TYPE_MAX);
76 j = job_new_raw(unit);
80 j->id = j->manager->current_job_id++;
83 /* We don't link it here, that's what job_dependency() is for */
88 void job_free(Job *j) {
92 assert(!j->installed);
93 assert(!j->transaction_prev);
94 assert(!j->transaction_next);
95 assert(!j->subject_list);
96 assert(!j->object_list);
99 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
101 if (j->in_dbus_queue)
102 LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
104 if (j->timer_watch.type != WATCH_INVALID) {
105 assert(j->timer_watch.type == WATCH_JOB_TIMER);
106 assert(j->timer_watch.data.job == j);
107 assert(j->timer_watch.fd >= 0);
109 assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
110 close_nointr_nofail(j->timer_watch.fd);
113 while ((cl = j->bus_client_list)) {
114 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
120 void job_uninstall(Job *j) {
123 assert(j->installed);
125 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
128 /* Detach from next 'bigger' objects */
130 /* daemon-reload should be transparent to job observers */
131 if (j->manager->n_reloading <= 0)
132 bus_job_send_removed_signal(j);
136 unit_add_to_gc_queue(j->unit);
138 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
139 j->installed = false;
142 static bool job_type_allows_late_merge(JobType t) {
143 /* Tells whether it is OK to merge a job of type 't' with an already
145 * Reloads cannot be merged this way. Think of the sequence:
146 * 1. Reload of a daemon is in progress; the daemon has already loaded
147 * its config file, but hasn't completed the reload operation yet.
148 * 2. Edit foo's config file.
149 * 3. Trigger another reload to have the daemon use the new config.
150 * Should the second reload job be merged into the first one, the daemon
151 * would not know about the new config.
152 * JOB_RESTART jobs on the other hand can be merged, because they get
153 * patched into JOB_START after stopping the unit. So if we see a
154 * JOB_RESTART running, it means the unit hasn't stopped yet and at
155 * this time the merge is still allowed. */
156 return t != JOB_RELOAD;
159 static void job_merge_into_installed(Job *j, Job *other) {
160 assert(j->installed);
161 assert(j->unit == other->unit);
163 if (j->type != JOB_NOP)
164 job_type_merge_and_collapse(&j->type, other->type, j->unit);
166 assert(other->type == JOB_NOP);
168 j->override = j->override || other->override;
171 Job* job_install(Job *j) {
175 assert(!j->installed);
176 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
178 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
182 if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
183 job_finish_and_invalidate(uj, JOB_CANCELED, true);
185 /* not conflicting, i.e. mergeable */
187 if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
188 (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
189 job_merge_into_installed(uj, j);
190 log_debug("Merged into installed job %s/%s as %u",
191 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
194 /* already running and not safe to merge into */
195 /* Patch uj to become a merged job and re-run it. */
196 /* XXX It should be safer to queue j to run after uj finishes, but it is
197 * not currently possible to have more than one installed job per unit. */
198 job_merge_into_installed(uj, j);
199 log_debug("Merged into running job, re-running: %s/%s as %u",
200 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
201 uj->state = JOB_WAITING;
207 /* Install the job */
210 j->manager->n_installed_jobs ++;
211 log_debug("Installed new job %s/%s as %u", j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
215 int job_install_deserialized(Job *j) {
218 assert(!j->installed);
220 if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
221 log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
225 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
228 log_debug("Unit %s already has a job installed. Not installing deserialized job.", j->unit->id);
233 log_debug("Reinstalled deserialized job %s/%s as %u", j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
237 JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
242 /* Adds a new job link, which encodes that the 'subject' job
243 * needs the 'object' job in some way. If 'subject' is NULL
244 * this means the 'anchor' job (i.e. the one the user
245 * explicitly asked for) is the requester. */
247 if (!(l = new0(JobDependency, 1)))
250 l->subject = subject;
252 l->matters = matters;
253 l->conflicts = conflicts;
256 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
258 LIST_PREPEND(JobDependency, object, object->object_list, l);
263 void job_dependency_free(JobDependency *l) {
267 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
269 LIST_REMOVE(JobDependency, object, l->object->object_list, l);
274 void job_dump(Job *j, FILE*f, const char *prefix) {
283 "%s\tAction: %s -> %s\n"
287 prefix, j->unit->id, job_type_to_string(j->type),
288 prefix, job_state_to_string(j->state),
289 prefix, yes_no(j->override));
293 * Merging is commutative, so imagine the matrix as symmetric. We store only
294 * its lower triangle to avoid duplication. We don't store the main diagonal,
295 * because A merged with A is simply A.
297 * If the resulting type is collapsed immediately afterwards (to get rid of
298 * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
299 * the following properties hold:
301 * Merging is associative! A merged with B merged with C is the same as
302 * A merged with C merged with B.
304 * Mergeability is transitive! If A can be merged with B and B with C then
307 * Also, if A merged with B cannot be merged with C, then either A or B cannot
308 * be merged with C either.
310 static const JobType job_merging_table[] = {
311 /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
312 /*********************************************************************************/
314 /*JOB_VERIFY_ACTIVE */ JOB_START,
315 /*JOB_STOP */ -1, -1,
316 /*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
317 /*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
320 JobType job_type_lookup_merge(JobType a, JobType b) {
321 assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
322 assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
323 assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
334 return job_merging_table[(a - 1) * a / 2 + b];
337 bool job_type_is_redundant(JobType a, UnitActiveState b) {
347 b == UNIT_INACTIVE ||
350 case JOB_VERIFY_ACTIVE:
361 b == UNIT_ACTIVATING;
364 assert_not_reached("Invalid job type");
368 void job_type_collapse(JobType *t, Unit *u) {
373 case JOB_TRY_RESTART:
374 s = unit_active_state(u);
375 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
381 case JOB_RELOAD_OR_START:
382 s = unit_active_state(u);
383 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
394 int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
395 JobType t = job_type_lookup_merge(*a, b);
399 job_type_collapse(a, u);
403 bool job_is_runnable(Job *j) {
408 assert(j->installed);
410 /* Checks whether there is any job running for the units this
411 * job needs to be running after (in the case of a 'positive'
412 * job type) or before (in the case of a 'negative' job
415 /* First check if there is an override */
419 if (j->type == JOB_NOP)
422 if (j->type == JOB_START ||
423 j->type == JOB_VERIFY_ACTIVE ||
424 j->type == JOB_RELOAD) {
426 /* Immediate result is that the job is or might be
427 * started. In this case lets wait for the
428 * dependencies, regardless whether they are
429 * starting or stopping something. */
431 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
436 /* Also, if something else is being stopped and we should
437 * change state after it, then lets wait. */
439 SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
441 (other->job->type == JOB_STOP ||
442 other->job->type == JOB_RESTART))
445 /* This means that for a service a and a service b where b
446 * shall be started after a:
448 * start a + start b → 1st step start a, 2nd step start b
449 * start a + stop b → 1st step stop b, 2nd step start a
450 * stop a + start b → 1st step stop a, 2nd step start b
451 * stop a + stop b → 1st step stop b, 2nd step stop a
453 * This has the side effect that restarts are properly
454 * synchronized too. */
459 static void job_change_type(Job *j, JobType newtype) {
460 log_debug("Converting job %s/%s -> %s/%s",
461 j->unit->id, job_type_to_string(j->type),
462 j->unit->id, job_type_to_string(newtype));
467 int job_run_and_invalidate(Job *j) {
473 assert(j->installed);
474 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
475 assert(j->in_run_queue);
477 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
478 j->in_run_queue = false;
480 if (j->state != JOB_WAITING)
483 if (!job_is_runnable(j))
486 j->state = JOB_RUNNING;
487 job_add_to_dbus_queue(j);
489 /* While we execute this operation the job might go away (for
490 * example: because it is replaced by a new, conflicting
491 * job.) To make sure we don't access a freed job later on we
492 * store the id here, so that we can verify the job is still
500 r = unit_start(j->unit);
502 /* If this unit cannot be started, then simply wait */
507 case JOB_VERIFY_ACTIVE: {
508 UnitActiveState t = unit_active_state(j->unit);
509 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
511 else if (t == UNIT_ACTIVATING)
520 r = unit_stop(j->unit);
522 /* If this unit cannot stopped, then simply wait. */
528 r = unit_reload(j->unit);
536 assert_not_reached("Unknown job type");
539 j = manager_get_job(m, id);
542 r = job_finish_and_invalidate(j, JOB_DONE, true);
543 else if (r == -ENOEXEC)
544 r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
545 else if (r == -EAGAIN)
546 j->state = JOB_WAITING;
548 r = job_finish_and_invalidate(j, JOB_FAILED, true);
554 static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
555 const UnitStatusMessageFormats *format_table;
559 assert(t < _JOB_TYPE_MAX);
561 format_table = &UNIT_VTABLE(u)->status_message_formats;
566 return format_table->finished_start_job[result];
567 else if (t == JOB_STOP || t == JOB_RESTART)
568 return format_table->finished_stop_job[result];
573 static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
578 assert(t < _JOB_TYPE_MAX);
580 format = job_get_status_message_format(u, t, result);
584 /* Return generic strings */
585 if (t == JOB_START) {
586 if (result == JOB_DONE)
587 return "Started %s.";
588 else if (result == JOB_FAILED)
589 return "Failed to start %s.";
590 else if (result == JOB_DEPENDENCY)
591 return "Dependency failed for %s.";
592 else if (result == JOB_TIMEOUT)
593 return "Timed out starting %s.";
594 } else if (t == JOB_STOP || t == JOB_RESTART) {
595 if (result == JOB_DONE)
596 return "Stopped %s.";
597 else if (result == JOB_FAILED)
598 return "Stopped (with error) %s.";
599 else if (result == JOB_TIMEOUT)
600 return "Timed out stoppping %s.";
601 } else if (t == JOB_RELOAD) {
602 if (result == JOB_DONE)
603 return "Reloaded %s.";
604 else if (result == JOB_FAILED)
605 return "Reload failed for %s.";
606 else if (result == JOB_TIMEOUT)
607 return "Timed out reloading %s.";
613 static void job_print_status_message(Unit *u, JobType t, JobResult result) {
618 assert(t < _JOB_TYPE_MAX);
620 if (t == JOB_START) {
621 format = job_get_status_message_format(u, t, result);
628 if (u->condition_result)
629 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
633 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
634 unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
638 unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
642 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
649 } else if (t == JOB_STOP || t == JOB_RESTART) {
651 format = job_get_status_message_format(u, t, result);
658 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
663 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
670 } else if (t == JOB_VERIFY_ACTIVE) {
672 /* When verify-active detects the unit is inactive, report it.
673 * Most likely a DEPEND warning from a requisiting unit will
674 * occur next and it's nice to see what was requisited. */
675 if (result == JOB_SKIPPED)
676 unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.", unit_description(u));
680 #pragma GCC diagnostic push
681 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
682 static void job_log_status_message(Unit *u, JobType t, JobResult result) {
688 assert(t < _JOB_TYPE_MAX);
690 /* Skip this if it goes to the console. since we already print
691 * to the console anyway... */
693 if (log_on_console())
696 format = job_get_status_message_format_try_harder(u, t, result);
700 snprintf(buf, sizeof(buf), format, unit_description(u));
703 if (t == JOB_START) {
706 mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
707 log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
710 "RESULT=%s", job_result_to_string(result),
714 } else if (t == JOB_STOP)
715 log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
716 MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
718 "RESULT=%s", job_result_to_string(result),
722 else if (t == JOB_RELOAD)
723 log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
724 MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
726 "RESULT=%s", job_result_to_string(result),
730 #pragma GCC diagnostic pop
732 int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
739 assert(j->installed);
740 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
747 log_debug("Job %s/%s finished, result=%s", u->id, job_type_to_string(t), job_result_to_string(result));
749 job_print_status_message(u, t, result);
750 job_log_status_message(u, t, result);
752 job_add_to_dbus_queue(j);
754 /* Patch restart jobs so that they become normal start jobs */
755 if (result == JOB_DONE && t == JOB_RESTART) {
757 job_change_type(j, JOB_START);
758 j->state = JOB_WAITING;
760 job_add_to_run_queue(j);
765 if (result == JOB_FAILED)
766 j->manager->n_failed_jobs ++;
771 /* Fail depending jobs on failure */
772 if (result != JOB_DONE && recursive) {
774 if (t == JOB_START ||
775 t == JOB_VERIFY_ACTIVE) {
777 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
779 (other->job->type == JOB_START ||
780 other->job->type == JOB_VERIFY_ACTIVE))
781 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
783 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
785 (other->job->type == JOB_START ||
786 other->job->type == JOB_VERIFY_ACTIVE))
787 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
789 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
791 !other->job->override &&
792 (other->job->type == JOB_START ||
793 other->job->type == JOB_VERIFY_ACTIVE))
794 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
796 } else if (t == JOB_STOP) {
798 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
800 (other->job->type == JOB_START ||
801 other->job->type == JOB_VERIFY_ACTIVE))
802 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
806 /* Trigger OnFailure dependencies that are not generated by
807 * the unit itself. We don't tread JOB_CANCELED as failure in
808 * this context. And JOB_FAILURE is already handled by the
810 if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
811 log_notice("Job %s/%s failed with result '%s'.",
813 job_type_to_string(t),
814 job_result_to_string(result));
816 unit_trigger_on_failure(u);
820 /* Try to start the next jobs that can be started */
821 SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
823 job_add_to_run_queue(other->job);
824 SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
826 job_add_to_run_queue(other->job);
828 manager_check_finished(u->manager);
833 int job_start_timer(Job *j) {
834 struct itimerspec its;
835 struct epoll_event ev;
839 if (j->unit->job_timeout <= 0 ||
840 j->timer_watch.type == WATCH_JOB_TIMER)
843 assert(j->timer_watch.type == WATCH_INVALID);
845 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
851 timespec_store(&its.it_value, j->unit->job_timeout);
853 if (timerfd_settime(fd, 0, &its, NULL) < 0) {
859 ev.data.ptr = &j->timer_watch;
862 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
867 j->timer_watch.type = WATCH_JOB_TIMER;
868 j->timer_watch.fd = fd;
869 j->timer_watch.data.job = j;
875 close_nointr_nofail(fd);
880 void job_add_to_run_queue(Job *j) {
882 assert(j->installed);
887 LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
888 j->in_run_queue = true;
891 void job_add_to_dbus_queue(Job *j) {
893 assert(j->installed);
895 if (j->in_dbus_queue)
898 /* We don't check if anybody is subscribed here, since this
899 * job might just have been created and not yet assigned to a
900 * connection/client. */
902 LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
903 j->in_dbus_queue = true;
906 char *job_dbus_path(Job *j) {
911 if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
917 void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
919 assert(w == &j->timer_watch);
921 log_warning("Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
922 job_finish_and_invalidate(j, JOB_TIMEOUT, true);
925 int job_serialize(Job *j, FILE *f, FDSet *fds) {
926 fprintf(f, "job-id=%u\n", j->id);
927 fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
928 fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
929 fprintf(f, "job-override=%s\n", yes_no(j->override));
930 fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
931 fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
932 /* Cannot save bus clients. Just note the fact that we're losing
933 * them. job_send_message() will fallback to broadcasting. */
934 fprintf(f, "job-forgot-bus-clients=%s\n",
935 yes_no(j->forgot_bus_clients || j->bus_client_list));
936 if (j->timer_watch.type == WATCH_JOB_TIMER) {
937 int copy = fdset_put_dup(fds, j->timer_watch.fd);
940 fprintf(f, "job-timer-watch-fd=%d\n", copy);
948 int job_deserialize(Job *j, FILE *f, FDSet *fds) {
950 char line[LINE_MAX], *l, *v;
953 if (!fgets(line, sizeof(line), f)) {
974 if (streq(l, "job-id")) {
975 if (safe_atou32(v, &j->id) < 0)
976 log_debug("Failed to parse job id value %s", v);
977 } else if (streq(l, "job-type")) {
978 JobType t = job_type_from_string(v);
980 log_debug("Failed to parse job type %s", v);
981 else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
982 log_debug("Cannot deserialize job of type %s", v);
985 } else if (streq(l, "job-state")) {
986 JobState s = job_state_from_string(v);
988 log_debug("Failed to parse job state %s", v);
991 } else if (streq(l, "job-override")) {
992 int b = parse_boolean(v);
994 log_debug("Failed to parse job override flag %s", v);
996 j->override = j->override || b;
997 } else if (streq(l, "job-sent-dbus-new-signal")) {
998 int b = parse_boolean(v);
1000 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
1002 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
1003 } else if (streq(l, "job-ignore-order")) {
1004 int b = parse_boolean(v);
1006 log_debug("Failed to parse job ignore_order flag %s", v);
1008 j->ignore_order = j->ignore_order || b;
1009 } else if (streq(l, "job-forgot-bus-clients")) {
1010 int b = parse_boolean(v);
1012 log_debug("Failed to parse job forgot_bus_clients flag %s", v);
1014 j->forgot_bus_clients = j->forgot_bus_clients || b;
1015 } else if (streq(l, "job-timer-watch-fd")) {
1017 if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
1018 log_debug("Failed to parse job-timer-watch-fd value %s", v);
1020 if (j->timer_watch.type == WATCH_JOB_TIMER)
1021 close_nointr_nofail(j->timer_watch.fd);
1023 j->timer_watch.type = WATCH_JOB_TIMER;
1024 j->timer_watch.fd = fdset_remove(fds, fd);
1025 j->timer_watch.data.job = j;
1031 int job_coldplug(Job *j) {
1032 struct epoll_event ev;
1034 if (j->timer_watch.type != WATCH_JOB_TIMER)
1038 ev.data.ptr = &j->timer_watch;
1039 ev.events = EPOLLIN;
1041 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
1047 static const char* const job_state_table[_JOB_STATE_MAX] = {
1048 [JOB_WAITING] = "waiting",
1049 [JOB_RUNNING] = "running"
1052 DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
1054 static const char* const job_type_table[_JOB_TYPE_MAX] = {
1055 [JOB_START] = "start",
1056 [JOB_VERIFY_ACTIVE] = "verify-active",
1057 [JOB_STOP] = "stop",
1058 [JOB_RELOAD] = "reload",
1059 [JOB_RELOAD_OR_START] = "reload-or-start",
1060 [JOB_RESTART] = "restart",
1061 [JOB_TRY_RESTART] = "try-restart",
1065 DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
1067 static const char* const job_mode_table[_JOB_MODE_MAX] = {
1068 [JOB_FAIL] = "fail",
1069 [JOB_REPLACE] = "replace",
1070 [JOB_ISOLATE] = "isolate",
1071 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
1072 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
1075 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
1077 static const char* const job_result_table[_JOB_RESULT_MAX] = {
1078 [JOB_DONE] = "done",
1079 [JOB_CANCELED] = "canceled",
1080 [JOB_TIMEOUT] = "timeout",
1081 [JOB_FAILED] = "failed",
1082 [JOB_DEPENDENCY] = "dependency",
1083 [JOB_SKIPPED] = "skipped"
1086 DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);