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>
31 #include "load-fragment.h"
32 #include "load-dropin.h"
36 Job* job_new(Unit *unit, JobType type) {
39 assert(type < _JOB_TYPE_MAX);
42 if (!(j = new0(Job, 1)))
45 j->manager = unit->manager;
46 j->id = j->manager->current_job_id++;
50 j->timer_watch.type = WATCH_INVALID;
52 /* We don't link it here, that's what job_dependency() is for */
57 void job_uninstall(Job *j) {
59 /* Detach from next 'bigger' objects */
61 bus_job_send_removed_signal(j);
63 if (j->unit->job == j) {
65 unit_add_to_gc_queue(j->unit);
68 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
72 void job_free(Job *j) {
74 assert(!j->installed);
75 assert(!j->transaction_prev);
76 assert(!j->transaction_next);
77 assert(!j->subject_list);
78 assert(!j->object_list);
81 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
84 LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
86 if (j->timer_watch.type != WATCH_INVALID) {
87 assert(j->timer_watch.type == WATCH_JOB_TIMER);
88 assert(j->timer_watch.data.job == j);
89 assert(j->timer_watch.fd >= 0);
91 assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
92 close_nointr_nofail(j->timer_watch.fd);
99 JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
104 /* Adds a new job link, which encodes that the 'subject' job
105 * needs the 'object' job in some way. If 'subject' is NULL
106 * this means the 'anchor' job (i.e. the one the user
107 * explicitly asked for) is the requester. */
109 if (!(l = new0(JobDependency, 1)))
112 l->subject = subject;
114 l->matters = matters;
115 l->conflicts = conflicts;
118 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
120 LIST_PREPEND(JobDependency, object, object->object_list, l);
125 void job_dependency_free(JobDependency *l) {
129 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
131 LIST_REMOVE(JobDependency, object, l->object->object_list, l);
136 void job_dump(Job *j, FILE*f, const char *prefix) {
145 "%s\tAction: %s -> %s\n"
149 prefix, j->unit->id, job_type_to_string(j->type),
150 prefix, job_state_to_string(j->state),
151 prefix, yes_no(j->override));
154 bool job_is_anchor(Job *j) {
159 LIST_FOREACH(object, l, j->object_list)
167 * Merging is commutative, so imagine the matrix as symmetric. We store only
168 * its lower triangle to avoid duplication. We don't store the main diagonal,
169 * because A merged with A is simply A.
171 * Merging is associative! A merged with B merged with C is the same as
172 * A merged with C merged with B.
174 * Mergeability is transitive! If A can be merged with B and B with C then
177 * Also, if A merged with B cannot be merged with C, then either A or B cannot
178 * be merged with C either.
180 static const JobType job_merging_table[] = {
181 /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD JOB_RELOAD_OR_START JOB_RESTART JOB_TRY_RESTART */
182 /************************************************************************************************************************************/
184 /*JOB_VERIFY_ACTIVE */ JOB_START,
185 /*JOB_STOP */ -1, -1,
186 /*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
187 /*JOB_RELOAD_OR_START*/ JOB_RELOAD_OR_START, JOB_RELOAD_OR_START, -1, JOB_RELOAD_OR_START,
188 /*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART, JOB_RESTART,
189 /*JOB_TRY_RESTART */ JOB_RESTART, JOB_TRY_RESTART, -1, JOB_TRY_RESTART, JOB_RESTART, JOB_RESTART,
192 JobType job_type_lookup_merge(JobType a, JobType b) {
193 assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX * (_JOB_TYPE_MAX - 1) / 2);
194 assert(a >= 0 && a < _JOB_TYPE_MAX);
195 assert(b >= 0 && b < _JOB_TYPE_MAX);
206 return job_merging_table[(a - 1) * a / 2 + b];
209 bool job_type_is_redundant(JobType a, UnitActiveState b) {
219 b == UNIT_INACTIVE ||
222 case JOB_VERIFY_ACTIVE:
231 case JOB_RELOAD_OR_START:
233 b == UNIT_ACTIVATING ||
238 b == UNIT_ACTIVATING;
240 case JOB_TRY_RESTART:
242 b == UNIT_ACTIVATING;
245 assert_not_reached("Invalid job type");
249 bool job_is_runnable(Job *j) {
254 assert(j->installed);
256 /* Checks whether there is any job running for the units this
257 * job needs to be running after (in the case of a 'positive'
258 * job type) or before (in the case of a 'negative' job
261 /* First check if there is an override */
265 if (j->type == JOB_START ||
266 j->type == JOB_VERIFY_ACTIVE ||
267 j->type == JOB_RELOAD ||
268 j->type == JOB_RELOAD_OR_START) {
270 /* Immediate result is that the job is or might be
271 * started. In this case lets wait for the
272 * dependencies, regardless whether they are
273 * starting or stopping something. */
275 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
280 /* Also, if something else is being stopped and we should
281 * change state after it, then lets wait. */
283 SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
285 (other->job->type == JOB_STOP ||
286 other->job->type == JOB_RESTART ||
287 other->job->type == JOB_TRY_RESTART))
290 /* This means that for a service a and a service b where b
291 * shall be started after a:
293 * start a + start b → 1st step start a, 2nd step start b
294 * start a + stop b → 1st step stop b, 2nd step start a
295 * stop a + start b → 1st step stop a, 2nd step start b
296 * stop a + stop b → 1st step stop b, 2nd step stop a
298 * This has the side effect that restarts are properly
299 * synchronized too. */
304 static void job_change_type(Job *j, JobType newtype) {
305 log_debug("Converting job %s/%s -> %s/%s",
306 j->unit->id, job_type_to_string(j->type),
307 j->unit->id, job_type_to_string(newtype));
312 int job_run_and_invalidate(Job *j) {
318 assert(j->installed);
320 if (j->in_run_queue) {
321 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
322 j->in_run_queue = false;
325 if (j->state != JOB_WAITING)
328 if (!job_is_runnable(j))
331 j->state = JOB_RUNNING;
332 job_add_to_dbus_queue(j);
334 /* While we execute this operation the job might go away (for
335 * example: because it is replaced by a new, conflicting
336 * job.) To make sure we don't access a freed job later on we
337 * store the id here, so that we can verify the job is still
344 case JOB_RELOAD_OR_START:
345 if (unit_active_state(j->unit) == UNIT_ACTIVE) {
346 job_change_type(j, JOB_RELOAD);
347 r = unit_reload(j->unit);
350 job_change_type(j, JOB_START);
354 r = unit_start(j->unit);
356 /* If this unit cannot be started, then simply wait */
361 case JOB_VERIFY_ACTIVE: {
362 UnitActiveState t = unit_active_state(j->unit);
363 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
365 else if (t == UNIT_ACTIVATING)
372 case JOB_TRY_RESTART:
373 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(j->unit))) {
377 job_change_type(j, JOB_RESTART);
382 r = unit_stop(j->unit);
384 /* If this unit cannot stopped, then simply wait. */
390 r = unit_reload(j->unit);
394 assert_not_reached("Unknown job type");
397 if ((j = manager_get_job(m, id))) {
399 r = job_finish_and_invalidate(j, JOB_DONE);
400 else if (r == -ENOEXEC)
401 r = job_finish_and_invalidate(j, JOB_SKIPPED);
402 else if (r == -EAGAIN)
403 j->state = JOB_WAITING;
405 r = job_finish_and_invalidate(j, JOB_FAILED);
411 static void job_print_status_message(Unit *u, JobType t, JobResult result) {
414 if (t == JOB_START) {
419 if (u->condition_result)
420 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, "Started %s", unit_description(u));
424 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, "Failed to start %s", unit_description(u));
425 unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
429 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " ABORT" ANSI_HIGHLIGHT_OFF, "Dependency failed. Aborted start of %s", unit_description(u));
433 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out starting %s", unit_description(u));
440 } else if (t == JOB_STOP) {
445 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out stopping %s", unit_description(u));
450 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, "Stopped %s", unit_description(u));
459 int job_finish_and_invalidate(Job *j, JobResult result) {
464 bool recursed = false;
467 assert(j->installed);
469 job_add_to_dbus_queue(j);
471 /* Patch restart jobs so that they become normal start jobs */
472 if (result == JOB_DONE && j->type == JOB_RESTART) {
474 job_change_type(j, JOB_START);
475 j->state = JOB_WAITING;
477 job_add_to_run_queue(j);
485 log_debug("Job %s/%s finished, result=%s", j->unit->id, job_type_to_string(j->type), job_result_to_string(result));
487 if (result == JOB_FAILED)
488 j->manager->n_failed_jobs ++;
495 job_print_status_message(u, t, result);
497 /* Fail depending jobs on failure */
498 if (result != JOB_DONE) {
500 if (t == JOB_START ||
501 t == JOB_VERIFY_ACTIVE ||
502 t == JOB_RELOAD_OR_START) {
504 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
506 (other->job->type == JOB_START ||
507 other->job->type == JOB_VERIFY_ACTIVE ||
508 other->job->type == JOB_RELOAD_OR_START)) {
509 job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
513 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
515 (other->job->type == JOB_START ||
516 other->job->type == JOB_VERIFY_ACTIVE ||
517 other->job->type == JOB_RELOAD_OR_START)) {
518 job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
522 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
524 !other->job->override &&
525 (other->job->type == JOB_START ||
526 other->job->type == JOB_VERIFY_ACTIVE ||
527 other->job->type == JOB_RELOAD_OR_START)) {
528 job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
532 } else if (t == JOB_STOP) {
534 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
536 (other->job->type == JOB_START ||
537 other->job->type == JOB_VERIFY_ACTIVE ||
538 other->job->type == JOB_RELOAD_OR_START)) {
539 job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
545 /* Trigger OnFailure dependencies that are not generated by
546 * the unit itself. We don't tread JOB_CANCELED as failure in
547 * this context. And JOB_FAILURE is already handled by the
549 if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
550 log_notice("Job %s/%s failed with result '%s'.",
552 job_type_to_string(t),
553 job_result_to_string(result));
555 unit_trigger_on_failure(u);
559 /* Try to start the next jobs that can be started */
560 SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
562 job_add_to_run_queue(other->job);
563 SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
565 job_add_to_run_queue(other->job);
567 manager_check_finished(u->manager);
572 int job_start_timer(Job *j) {
573 struct itimerspec its;
574 struct epoll_event ev;
578 if (j->unit->job_timeout <= 0 ||
579 j->timer_watch.type == WATCH_JOB_TIMER)
582 assert(j->timer_watch.type == WATCH_INVALID);
584 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
590 timespec_store(&its.it_value, j->unit->job_timeout);
592 if (timerfd_settime(fd, 0, &its, NULL) < 0) {
598 ev.data.ptr = &j->timer_watch;
601 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
606 j->timer_watch.type = WATCH_JOB_TIMER;
607 j->timer_watch.fd = fd;
608 j->timer_watch.data.job = j;
614 close_nointr_nofail(fd);
619 void job_add_to_run_queue(Job *j) {
621 assert(j->installed);
626 LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
627 j->in_run_queue = true;
630 void job_add_to_dbus_queue(Job *j) {
632 assert(j->installed);
634 if (j->in_dbus_queue)
637 /* We don't check if anybody is subscribed here, since this
638 * job might just have been created and not yet assigned to a
639 * connection/client. */
641 LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
642 j->in_dbus_queue = true;
645 char *job_dbus_path(Job *j) {
650 if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
656 void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
658 assert(w == &j->timer_watch);
660 log_warning("Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
661 job_finish_and_invalidate(j, JOB_TIMEOUT);
664 static const char* const job_state_table[_JOB_STATE_MAX] = {
665 [JOB_WAITING] = "waiting",
666 [JOB_RUNNING] = "running"
669 DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
671 static const char* const job_type_table[_JOB_TYPE_MAX] = {
672 [JOB_START] = "start",
673 [JOB_VERIFY_ACTIVE] = "verify-active",
675 [JOB_RELOAD] = "reload",
676 [JOB_RELOAD_OR_START] = "reload-or-start",
677 [JOB_RESTART] = "restart",
678 [JOB_TRY_RESTART] = "try-restart",
681 DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
683 static const char* const job_mode_table[_JOB_MODE_MAX] = {
685 [JOB_REPLACE] = "replace",
686 [JOB_ISOLATE] = "isolate",
687 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
688 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
691 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
693 static const char* const job_result_table[_JOB_RESULT_MAX] = {
695 [JOB_CANCELED] = "canceled",
696 [JOB_TIMEOUT] = "timeout",
697 [JOB_FAILED] = "failed",
698 [JOB_DEPENDENCY] = "dependency",
699 [JOB_SKIPPED] = "skipped"
702 DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);