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(Manager *m, JobType type, Unit *unit) {
40 assert(type < _JOB_TYPE_MAX);
43 if (!(j = new0(Job, 1)))
47 j->id = m->current_job_id++;
51 j->timer_watch.type = WATCH_INVALID;
53 /* We don't link it here, that's what job_dependency() is for */
58 void job_uninstall(Job *j) {
60 /* Detach from next 'bigger' objects */
62 bus_job_send_removed_signal(j);
64 if (j->unit->job == j) {
66 unit_add_to_gc_queue(j->unit);
69 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
73 void job_free(Job *j) {
75 assert(!j->installed);
76 assert(!j->transaction_prev);
77 assert(!j->transaction_next);
78 assert(!j->subject_list);
79 assert(!j->object_list);
82 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
85 LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
87 if (j->timer_watch.type != WATCH_INVALID) {
88 assert(j->timer_watch.type == WATCH_JOB_TIMER);
89 assert(j->timer_watch.data.job == j);
90 assert(j->timer_watch.fd >= 0);
92 assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
93 close_nointr_nofail(j->timer_watch.fd);
100 JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts, Transaction *tr) {
105 /* Adds a new job link, which encodes that the 'subject' job
106 * needs the 'object' job in some way. If 'subject' is NULL
107 * this means the 'anchor' job (i.e. the one the user
108 * explicitly asked for) is the requester. */
110 if (!(l = new0(JobDependency, 1)))
113 l->subject = subject;
115 l->matters = matters;
116 l->conflicts = conflicts;
119 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
121 LIST_PREPEND(JobDependency, subject, tr->anchor, l);
123 LIST_PREPEND(JobDependency, object, object->object_list, l);
128 void job_dependency_free(JobDependency *l, Transaction *tr) {
132 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
134 LIST_REMOVE(JobDependency, subject, tr->anchor, l);
136 LIST_REMOVE(JobDependency, object, l->object->object_list, l);
141 void job_dump(Job *j, FILE*f, const char *prefix) {
150 "%s\tAction: %s -> %s\n"
154 prefix, j->unit->id, job_type_to_string(j->type),
155 prefix, job_state_to_string(j->state),
156 prefix, yes_no(j->override));
159 bool job_is_anchor(Job *j) {
164 LIST_FOREACH(object, l, j->object_list)
172 * Merging is commutative, so imagine the matrix as symmetric. We store only
173 * its lower triangle to avoid duplication. We don't store the main diagonal,
174 * because A merged with A is simply A.
176 * Merging is associative! A merged with B merged with C is the same as
177 * A merged with C merged with B.
179 * Mergeability is transitive! If A can be merged with B and B with C then
182 * Also, if A merged with B cannot be merged with C, then either A or B cannot
183 * be merged with C either.
185 static const JobType job_merging_table[] = {
186 /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD JOB_RELOAD_OR_START JOB_RESTART JOB_TRY_RESTART */
187 /************************************************************************************************************************************/
189 /*JOB_VERIFY_ACTIVE */ JOB_START,
190 /*JOB_STOP */ -1, -1,
191 /*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
192 /*JOB_RELOAD_OR_START*/ JOB_RELOAD_OR_START, JOB_RELOAD_OR_START, -1, JOB_RELOAD_OR_START,
193 /*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART, JOB_RESTART,
194 /*JOB_TRY_RESTART */ JOB_RESTART, JOB_TRY_RESTART, -1, JOB_TRY_RESTART, JOB_RESTART, JOB_RESTART,
197 JobType job_type_lookup_merge(JobType a, JobType b) {
198 assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX * (_JOB_TYPE_MAX - 1) / 2);
199 assert(a >= 0 && a < _JOB_TYPE_MAX);
200 assert(b >= 0 && b < _JOB_TYPE_MAX);
211 return job_merging_table[(a - 1) * a / 2 + b];
214 bool job_type_is_redundant(JobType a, UnitActiveState b) {
224 b == UNIT_INACTIVE ||
227 case JOB_VERIFY_ACTIVE:
236 case JOB_RELOAD_OR_START:
238 b == UNIT_ACTIVATING ||
243 b == UNIT_ACTIVATING;
245 case JOB_TRY_RESTART:
247 b == UNIT_ACTIVATING;
250 assert_not_reached("Invalid job type");
254 bool job_is_runnable(Job *j) {
259 assert(j->installed);
261 /* Checks whether there is any job running for the units this
262 * job needs to be running after (in the case of a 'positive'
263 * job type) or before (in the case of a 'negative' job
266 /* First check if there is an override */
270 if (j->type == JOB_START ||
271 j->type == JOB_VERIFY_ACTIVE ||
272 j->type == JOB_RELOAD ||
273 j->type == JOB_RELOAD_OR_START) {
275 /* Immediate result is that the job is or might be
276 * started. In this case lets wait for the
277 * dependencies, regardless whether they are
278 * starting or stopping something. */
280 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
285 /* Also, if something else is being stopped and we should
286 * change state after it, then lets wait. */
288 SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
290 (other->job->type == JOB_STOP ||
291 other->job->type == JOB_RESTART ||
292 other->job->type == JOB_TRY_RESTART))
295 /* This means that for a service a and a service b where b
296 * shall be started after a:
298 * start a + start b → 1st step start a, 2nd step start b
299 * start a + stop b → 1st step stop b, 2nd step start a
300 * stop a + start b → 1st step stop a, 2nd step start b
301 * stop a + stop b → 1st step stop b, 2nd step stop a
303 * This has the side effect that restarts are properly
304 * synchronized too. */
309 static void job_change_type(Job *j, JobType newtype) {
310 log_debug("Converting job %s/%s -> %s/%s",
311 j->unit->id, job_type_to_string(j->type),
312 j->unit->id, job_type_to_string(newtype));
317 int job_run_and_invalidate(Job *j) {
323 assert(j->installed);
325 if (j->in_run_queue) {
326 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
327 j->in_run_queue = false;
330 if (j->state != JOB_WAITING)
333 if (!job_is_runnable(j))
336 j->state = JOB_RUNNING;
337 job_add_to_dbus_queue(j);
339 /* While we execute this operation the job might go away (for
340 * example: because it is replaced by a new, conflicting
341 * job.) To make sure we don't access a freed job later on we
342 * store the id here, so that we can verify the job is still
349 case JOB_RELOAD_OR_START:
350 if (unit_active_state(j->unit) == UNIT_ACTIVE) {
351 job_change_type(j, JOB_RELOAD);
352 r = unit_reload(j->unit);
355 job_change_type(j, JOB_START);
359 r = unit_start(j->unit);
361 /* If this unit cannot be started, then simply wait */
366 case JOB_VERIFY_ACTIVE: {
367 UnitActiveState t = unit_active_state(j->unit);
368 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
370 else if (t == UNIT_ACTIVATING)
377 case JOB_TRY_RESTART:
378 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(j->unit))) {
382 job_change_type(j, JOB_RESTART);
387 r = unit_stop(j->unit);
389 /* If this unit cannot stopped, then simply wait. */
395 r = unit_reload(j->unit);
399 assert_not_reached("Unknown job type");
402 if ((j = manager_get_job(m, id))) {
404 r = job_finish_and_invalidate(j, JOB_DONE);
405 else if (r == -ENOEXEC)
406 r = job_finish_and_invalidate(j, JOB_SKIPPED);
407 else if (r == -EAGAIN)
408 j->state = JOB_WAITING;
410 r = job_finish_and_invalidate(j, JOB_FAILED);
416 static void job_print_status_message(Unit *u, JobType t, JobResult result) {
419 if (t == JOB_START) {
424 if (u->condition_result)
425 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, "Started %s", unit_description(u));
429 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, "Failed to start %s", unit_description(u));
430 unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
434 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " ABORT" ANSI_HIGHLIGHT_OFF, "Dependency failed. Aborted start of %s", unit_description(u));
438 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out starting %s", unit_description(u));
445 } else if (t == JOB_STOP) {
450 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out stopping %s", unit_description(u));
455 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, "Stopped %s", unit_description(u));
464 int job_finish_and_invalidate(Job *j, JobResult result) {
469 bool recursed = false;
472 assert(j->installed);
474 job_add_to_dbus_queue(j);
476 /* Patch restart jobs so that they become normal start jobs */
477 if (result == JOB_DONE && j->type == JOB_RESTART) {
479 job_change_type(j, JOB_START);
480 j->state = JOB_WAITING;
482 job_add_to_run_queue(j);
490 log_debug("Job %s/%s finished, result=%s", j->unit->id, job_type_to_string(j->type), job_result_to_string(result));
492 if (result == JOB_FAILED)
493 j->manager->n_failed_jobs ++;
500 job_print_status_message(u, t, result);
502 /* Fail depending jobs on failure */
503 if (result != JOB_DONE) {
505 if (t == JOB_START ||
506 t == JOB_VERIFY_ACTIVE ||
507 t == JOB_RELOAD_OR_START) {
509 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
511 (other->job->type == JOB_START ||
512 other->job->type == JOB_VERIFY_ACTIVE ||
513 other->job->type == JOB_RELOAD_OR_START)) {
514 job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
518 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
520 (other->job->type == JOB_START ||
521 other->job->type == JOB_VERIFY_ACTIVE ||
522 other->job->type == JOB_RELOAD_OR_START)) {
523 job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
527 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
529 !other->job->override &&
530 (other->job->type == JOB_START ||
531 other->job->type == JOB_VERIFY_ACTIVE ||
532 other->job->type == JOB_RELOAD_OR_START)) {
533 job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
537 } else if (t == JOB_STOP) {
539 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
541 (other->job->type == JOB_START ||
542 other->job->type == JOB_VERIFY_ACTIVE ||
543 other->job->type == JOB_RELOAD_OR_START)) {
544 job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
550 /* Trigger OnFailure dependencies that are not generated by
551 * the unit itself. We don't tread JOB_CANCELED as failure in
552 * this context. And JOB_FAILURE is already handled by the
554 if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
555 log_notice("Job %s/%s failed with result '%s'.",
557 job_type_to_string(t),
558 job_result_to_string(result));
560 unit_trigger_on_failure(u);
564 /* Try to start the next jobs that can be started */
565 SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
567 job_add_to_run_queue(other->job);
568 SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
570 job_add_to_run_queue(other->job);
572 manager_check_finished(u->manager);
577 int job_start_timer(Job *j) {
578 struct itimerspec its;
579 struct epoll_event ev;
583 if (j->unit->job_timeout <= 0 ||
584 j->timer_watch.type == WATCH_JOB_TIMER)
587 assert(j->timer_watch.type == WATCH_INVALID);
589 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
595 timespec_store(&its.it_value, j->unit->job_timeout);
597 if (timerfd_settime(fd, 0, &its, NULL) < 0) {
603 ev.data.ptr = &j->timer_watch;
606 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
611 j->timer_watch.type = WATCH_JOB_TIMER;
612 j->timer_watch.fd = fd;
613 j->timer_watch.data.job = j;
619 close_nointr_nofail(fd);
624 void job_add_to_run_queue(Job *j) {
626 assert(j->installed);
631 LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
632 j->in_run_queue = true;
635 void job_add_to_dbus_queue(Job *j) {
637 assert(j->installed);
639 if (j->in_dbus_queue)
642 /* We don't check if anybody is subscribed here, since this
643 * job might just have been created and not yet assigned to a
644 * connection/client. */
646 LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
647 j->in_dbus_queue = true;
650 char *job_dbus_path(Job *j) {
655 if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
661 void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
663 assert(w == &j->timer_watch);
665 log_warning("Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
666 job_finish_and_invalidate(j, JOB_TIMEOUT);
669 static const char* const job_state_table[_JOB_STATE_MAX] = {
670 [JOB_WAITING] = "waiting",
671 [JOB_RUNNING] = "running"
674 DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
676 static const char* const job_type_table[_JOB_TYPE_MAX] = {
677 [JOB_START] = "start",
678 [JOB_VERIFY_ACTIVE] = "verify-active",
680 [JOB_RELOAD] = "reload",
681 [JOB_RELOAD_OR_START] = "reload-or-start",
682 [JOB_RESTART] = "restart",
683 [JOB_TRY_RESTART] = "try-restart",
686 DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
688 static const char* const job_mode_table[_JOB_MODE_MAX] = {
690 [JOB_REPLACE] = "replace",
691 [JOB_ISOLATE] = "isolate",
692 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
693 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
696 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
698 static const char* const job_result_table[_JOB_RESULT_MAX] = {
700 [JOB_CANCELED] = "canceled",
701 [JOB_TIMEOUT] = "timeout",
702 [JOB_FAILED] = "failed",
703 [JOB_DEPENDENCY] = "dependency",
704 [JOB_SKIPPED] = "skipped"
707 DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);