]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/job.c
systemctl: make "systemctl default" use "isolate" job mode
[thirdparty/systemd.git] / src / core / job.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60918275 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
a7334b09
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
60918275 22#include <assert.h>
1ffba6fe 23#include <errno.h>
faf919f1
LP
24#include <sys/timerfd.h>
25#include <sys/epoll.h>
60918275 26
877d54e9
LP
27#include "systemd/sd-id128.h"
28#include "systemd/sd-messages.h"
94f04347
LP
29#include "set.h"
30#include "unit.h"
60918275 31#include "macro.h"
94f04347
LP
32#include "strv.h"
33#include "load-fragment.h"
34#include "load-dropin.h"
f50e0a01 35#include "log.h"
4139c1b2 36#include "dbus-job.h"
c65eb836
LP
37#include "special.h"
38#include "sync.h"
39#include "virt.h"
60918275 40
97e6a119
MS
41JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
42 JobBusClient *cl;
43 size_t name_len;
44
45 name_len = strlen(name);
46 cl = malloc0(sizeof(JobBusClient) + name_len + 1);
47 if (!cl)
48 return NULL;
49
50 cl->bus = connection;
51 memcpy(cl->name, name, name_len + 1);
52 return cl;
53}
54
39a18c60 55Job* job_new_raw(Unit *unit) {
60918275
LP
56 Job *j;
57
39a18c60
MS
58 /* used for deserialization */
59
87f0e418 60 assert(unit);
60918275 61
39a18c60
MS
62 j = new0(Job, 1);
63 if (!j)
60918275
LP
64 return NULL;
65
668ad332 66 j->manager = unit->manager;
87f0e418 67 j->unit = unit;
e0209d83 68 j->type = _JOB_TYPE_INVALID;
faf919f1
LP
69 j->timer_watch.type = WATCH_INVALID;
70
39a18c60
MS
71 return j;
72}
73
74Job* job_new(Unit *unit, JobType type) {
75 Job *j;
76
77 assert(type < _JOB_TYPE_MAX);
78
79 j = job_new_raw(unit);
80 if (!j)
81 return NULL;
82
83 j->id = j->manager->current_job_id++;
84 j->type = type;
85
e5b5ae50 86 /* We don't link it here, that's what job_dependency() is for */
60918275
LP
87
88 return j;
89}
90
97e7d748 91void job_free(Job *j) {
97e6a119
MS
92 JobBusClient *cl;
93
97e7d748
MS
94 assert(j);
95 assert(!j->installed);
02a3bcc6
MS
96 assert(!j->transaction_prev);
97 assert(!j->transaction_next);
98 assert(!j->subject_list);
99 assert(!j->object_list);
60918275 100
c1e1601e
LP
101 if (j->in_run_queue)
102 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
103
104 if (j->in_dbus_queue)
105 LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
106
faf919f1
LP
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);
111
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);
114 }
115
97e6a119
MS
116 while ((cl = j->bus_client_list)) {
117 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
118 free(cl);
119 }
60918275
LP
120 free(j);
121}
a66d02c3 122
05d576f1 123void job_uninstall(Job *j) {
e0209d83
MS
124 Job **pj;
125
05d576f1 126 assert(j->installed);
e0209d83
MS
127
128 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
129 assert(*pj == j);
130
05d576f1
MS
131 /* Detach from next 'bigger' objects */
132
39a18c60
MS
133 /* daemon-reload should be transparent to job observers */
134 if (j->manager->n_reloading <= 0)
135 bus_job_send_removed_signal(j);
05d576f1 136
e0209d83
MS
137 *pj = NULL;
138
d6a093d0 139 unit_add_to_gc_queue(j->unit);
05d576f1
MS
140
141 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
142 j->installed = false;
143}
144
656bbffc
MS
145static bool job_type_allows_late_merge(JobType t) {
146 /* Tells whether it is OK to merge a job of type 't' with an already
147 * running job.
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. */
e0209d83 159 return t != JOB_RELOAD;
656bbffc
MS
160}
161
162static void job_merge_into_installed(Job *j, Job *other) {
163 assert(j->installed);
164 assert(j->unit == other->unit);
165
e0209d83
MS
166 if (j->type != JOB_NOP)
167 job_type_merge_and_collapse(&j->type, other->type, j->unit);
168 else
169 assert(other->type == JOB_NOP);
656bbffc
MS
170
171 j->override = j->override || other->override;
e45460d6 172 j->ignore_order = j->ignore_order || other->ignore_order;
656bbffc
MS
173}
174
175Job* job_install(Job *j) {
e0209d83
MS
176 Job **pj;
177 Job *uj;
05d576f1 178
656bbffc 179 assert(!j->installed);
e0209d83
MS
180 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
181
182 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
183 uj = *pj;
656bbffc 184
05d576f1 185 if (uj) {
e0209d83 186 if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
1abc85b8 187 job_finish_and_invalidate(uj, JOB_CANCELED, false);
656bbffc
MS
188 else {
189 /* not conflicting, i.e. mergeable */
190
e0209d83 191 if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
656bbffc
MS
192 (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
193 job_merge_into_installed(uj, j);
66870f90
ZJS
194 log_debug_unit(uj->unit->id,
195 "Merged into installed job %s/%s as %u",
196 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
656bbffc
MS
197 return uj;
198 } else {
199 /* already running and not safe to merge into */
200 /* Patch uj to become a merged job and re-run it. */
201 /* XXX It should be safer to queue j to run after uj finishes, but it is
202 * not currently possible to have more than one installed job per unit. */
203 job_merge_into_installed(uj, j);
66870f90
ZJS
204 log_debug_unit(uj->unit->id,
205 "Merged into running job, re-running: %s/%s as %u",
206 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
656bbffc
MS
207 uj->state = JOB_WAITING;
208 return uj;
209 }
210 }
05d576f1
MS
211 }
212
656bbffc 213 /* Install the job */
e0209d83 214 *pj = j;
05d576f1
MS
215 j->installed = true;
216 j->manager->n_installed_jobs ++;
66870f90
ZJS
217 log_debug_unit(j->unit->id,
218 "Installed new job %s/%s as %u",
219 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
656bbffc 220 return j;
05d576f1
MS
221}
222
e0209d83
MS
223int job_install_deserialized(Job *j) {
224 Job **pj;
225
39a18c60
MS
226 assert(!j->installed);
227
e0209d83
MS
228 if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
229 log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
230 return -EINVAL;
231 }
232
233 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
234
235 if (*pj) {
66870f90
ZJS
236 log_debug_unit(j->unit->id,
237 "Unit %s already has a job installed. Not installing deserialized job.",
238 j->unit->id);
e0209d83 239 return -EEXIST;
39a18c60 240 }
e0209d83 241 *pj = j;
39a18c60 242 j->installed = true;
66870f90
ZJS
243 log_debug_unit(j->unit->id,
244 "Reinstalled deserialized job %s/%s as %u",
245 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
e0209d83 246 return 0;
39a18c60
MS
247}
248
1da4264f 249JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
e5b5ae50
LP
250 JobDependency *l;
251
252 assert(object);
253
254 /* Adds a new job link, which encodes that the 'subject' job
255 * needs the 'object' job in some way. If 'subject' is NULL
256 * this means the 'anchor' job (i.e. the one the user
35b8ca3a 257 * explicitly asked for) is the requester. */
e5b5ae50 258
ceed3570 259 if (!(l = new0(JobDependency, 1)))
e5b5ae50
LP
260 return NULL;
261
262 l->subject = subject;
263 l->object = object;
264 l->matters = matters;
69dd2852 265 l->conflicts = conflicts;
e5b5ae50 266
44d8db9e
LP
267 if (subject)
268 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
e5b5ae50 269
44d8db9e 270 LIST_PREPEND(JobDependency, object, object->object_list, l);
e5b5ae50
LP
271
272 return l;
273}
274
1da4264f 275void job_dependency_free(JobDependency *l) {
e5b5ae50
LP
276 assert(l);
277
44d8db9e
LP
278 if (l->subject)
279 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
e5b5ae50 280
44d8db9e 281 LIST_REMOVE(JobDependency, object, l->object->object_list, l);
e5b5ae50
LP
282
283 free(l);
284}
285
1ffba6fe 286void job_dump(Job *j, FILE*f, const char *prefix) {
a66d02c3
LP
287 assert(j);
288 assert(f);
289
9eb63b3c
LP
290 if (!prefix)
291 prefix = "";
292
ceed3570 293 fprintf(f,
40d50879
LP
294 "%s-> Job %u:\n"
295 "%s\tAction: %s -> %s\n"
5cb5a6ff
LP
296 "%s\tState: %s\n"
297 "%s\tForced: %s\n",
ceed3570 298 prefix, j->id,
ac155bb8 299 prefix, j->unit->id, job_type_to_string(j->type),
94f04347 300 prefix, job_state_to_string(j->state),
9e2f7c11 301 prefix, yes_no(j->override));
a66d02c3 302}
e5b5ae50 303
348e27fe
MS
304/*
305 * Merging is commutative, so imagine the matrix as symmetric. We store only
306 * its lower triangle to avoid duplication. We don't store the main diagonal,
307 * because A merged with A is simply A.
308 *
e0209d83
MS
309 * If the resulting type is collapsed immediately afterwards (to get rid of
310 * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
311 * the following properties hold:
312 *
348e27fe
MS
313 * Merging is associative! A merged with B merged with C is the same as
314 * A merged with C merged with B.
315 *
316 * Mergeability is transitive! If A can be merged with B and B with C then
317 * A also with C.
318 *
319 * Also, if A merged with B cannot be merged with C, then either A or B cannot
320 * be merged with C either.
321 */
322static const JobType job_merging_table[] = {
e0209d83
MS
323/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
324/*********************************************************************************/
348e27fe
MS
325/*JOB_START */
326/*JOB_VERIFY_ACTIVE */ JOB_START,
327/*JOB_STOP */ -1, -1,
328/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
e0209d83 329/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
348e27fe
MS
330};
331
332JobType job_type_lookup_merge(JobType a, JobType b) {
e0209d83
MS
333 assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
334 assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
335 assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
1ffba6fe
LP
336
337 if (a == b)
348e27fe 338 return a;
1ffba6fe 339
348e27fe
MS
340 if (a < b) {
341 JobType tmp = a;
342 a = b;
343 b = tmp;
1ffba6fe 344 }
e094e853 345
348e27fe 346 return job_merging_table[(a - 1) * a / 2 + b];
e094e853 347}
cd2dbd7d 348
593fbdd2
LP
349bool job_type_is_redundant(JobType a, UnitActiveState b) {
350 switch (a) {
351
352 case JOB_START:
353 return
354 b == UNIT_ACTIVE ||
032ff4af 355 b == UNIT_RELOADING;
593fbdd2
LP
356
357 case JOB_STOP:
358 return
6124958c 359 b == UNIT_INACTIVE ||
fdf20a31 360 b == UNIT_FAILED;
593fbdd2
LP
361
362 case JOB_VERIFY_ACTIVE:
363 return
364 b == UNIT_ACTIVE ||
032ff4af 365 b == UNIT_RELOADING;
593fbdd2
LP
366
367 case JOB_RELOAD:
368 return
032ff4af 369 b == UNIT_RELOADING;
593fbdd2 370
593fbdd2
LP
371 case JOB_RESTART:
372 return
373 b == UNIT_ACTIVATING;
374
e0209d83
MS
375 default:
376 assert_not_reached("Invalid job type");
377 }
378}
379
380void job_type_collapse(JobType *t, Unit *u) {
381 UnitActiveState s;
382
383 switch (*t) {
384
593fbdd2 385 case JOB_TRY_RESTART:
e0209d83
MS
386 s = unit_active_state(u);
387 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
388 *t = JOB_NOP;
389 else
390 *t = JOB_RESTART;
391 break;
392
393 case JOB_RELOAD_OR_START:
394 s = unit_active_state(u);
395 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
396 *t = JOB_START;
397 else
398 *t = JOB_RELOAD;
399 break;
593fbdd2
LP
400
401 default:
e0209d83 402 ;
593fbdd2
LP
403 }
404}
405
e0209d83
MS
406int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
407 JobType t = job_type_lookup_merge(*a, b);
408 if (t < 0)
409 return -EEXIST;
410 *a = t;
411 job_type_collapse(a, u);
412 return 0;
413}
414
5cb5a6ff 415bool job_is_runnable(Job *j) {
034c6ed7 416 Iterator i;
87f0e418 417 Unit *other;
5cb5a6ff
LP
418
419 assert(j);
ac1135be 420 assert(j->installed);
5cb5a6ff 421
87f0e418 422 /* Checks whether there is any job running for the units this
5cb5a6ff 423 * job needs to be running after (in the case of a 'positive'
e67c3609
LP
424 * job type) or before (in the case of a 'negative' job
425 * type. */
426
427 /* First check if there is an override */
cebe0d41 428 if (j->ignore_order)
e67c3609 429 return true;
5cb5a6ff 430
e0209d83
MS
431 if (j->type == JOB_NOP)
432 return true;
433
5cb5a6ff
LP
434 if (j->type == JOB_START ||
435 j->type == JOB_VERIFY_ACTIVE ||
e0209d83 436 j->type == JOB_RELOAD) {
5cb5a6ff
LP
437
438 /* Immediate result is that the job is or might be
439 * started. In this case lets wait for the
440 * dependencies, regardless whether they are
441 * starting or stopping something. */
442
ac155bb8
MS
443 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
444 if (other->job)
5cb5a6ff
LP
445 return false;
446 }
447
448 /* Also, if something else is being stopped and we should
449 * change state after it, then lets wait. */
450
ac155bb8
MS
451 SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
452 if (other->job &&
453 (other->job->type == JOB_STOP ||
e0209d83 454 other->job->type == JOB_RESTART))
5cb5a6ff
LP
455 return false;
456
457 /* This means that for a service a and a service b where b
458 * shall be started after a:
459 *
460 * start a + start b → 1st step start a, 2nd step start b
461 * start a + stop b → 1st step stop b, 2nd step start a
462 * stop a + start b → 1st step stop a, 2nd step start b
463 * stop a + stop b → 1st step stop b, 2nd step stop a
464 *
465 * This has the side effect that restarts are properly
466 * synchronized too. */
467
468 return true;
469}
470
bbd1a837 471static void job_change_type(Job *j, JobType newtype) {
66870f90
ZJS
472 log_debug_unit(j->unit->id,
473 "Converting job %s/%s -> %s/%s",
474 j->unit->id, job_type_to_string(j->type),
475 j->unit->id, job_type_to_string(newtype));
bbd1a837
MS
476
477 j->type = newtype;
478}
479
5cb5a6ff
LP
480int job_run_and_invalidate(Job *j) {
481 int r;
2cf19a7a
LP
482 uint32_t id;
483 Manager *m;
ac1135be 484
5cb5a6ff 485 assert(j);
ac1135be 486 assert(j->installed);
e0209d83 487 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
66aa6f7f 488 assert(j->in_run_queue);
5cb5a6ff 489
66aa6f7f
MS
490 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
491 j->in_run_queue = false;
5cb5a6ff
LP
492
493 if (j->state != JOB_WAITING)
494 return 0;
495
034c6ed7
LP
496 if (!job_is_runnable(j))
497 return -EAGAIN;
498
83c60c9f 499 j->state = JOB_RUNNING;
c1e1601e 500 job_add_to_dbus_queue(j);
83c60c9f 501
2cf19a7a
LP
502 /* While we execute this operation the job might go away (for
503 * example: because it is replaced by a new, conflicting
504 * job.) To make sure we don't access a freed job later on we
505 * store the id here, so that we can verify the job is still
506 * valid. */
507 id = j->id;
508 m = j->manager;
509
5cb5a6ff
LP
510 switch (j->type) {
511
512 case JOB_START:
87f0e418 513 r = unit_start(j->unit);
57339f47 514
dd17d388 515 /* If this unit cannot be started, then simply wait */
5cb5a6ff
LP
516 if (r == -EBADR)
517 r = 0;
518 break;
519
520 case JOB_VERIFY_ACTIVE: {
87f0e418
LP
521 UnitActiveState t = unit_active_state(j->unit);
522 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
5cb5a6ff 523 r = -EALREADY;
87f0e418 524 else if (t == UNIT_ACTIVATING)
5cb5a6ff
LP
525 r = -EAGAIN;
526 else
527 r = -ENOEXEC;
528 break;
529 }
530
531 case JOB_STOP:
dd17d388 532 case JOB_RESTART:
87f0e418 533 r = unit_stop(j->unit);
57339f47 534
dd17d388 535 /* If this unit cannot stopped, then simply wait. */
57339f47
LP
536 if (r == -EBADR)
537 r = 0;
5cb5a6ff
LP
538 break;
539
540 case JOB_RELOAD:
87f0e418 541 r = unit_reload(j->unit);
5cb5a6ff
LP
542 break;
543
e0209d83
MS
544 case JOB_NOP:
545 r = -EALREADY;
546 break;
547
5cb5a6ff 548 default:
44d8db9e 549 assert_not_reached("Unknown job type");
5cb5a6ff
LP
550 }
551
e0209d83
MS
552 j = manager_get_job(m, id);
553 if (j) {
2cf19a7a 554 if (r == -EALREADY)
5273510e 555 r = job_finish_and_invalidate(j, JOB_DONE, true);
d68201e9 556 else if (r == -ENOEXEC)
5273510e 557 r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
2cf19a7a
LP
558 else if (r == -EAGAIN)
559 j->state = JOB_WAITING;
560 else if (r < 0)
5273510e 561 r = job_finish_and_invalidate(j, JOB_FAILED, true);
2cf19a7a 562 }
5cb5a6ff
LP
563
564 return r;
565}
566
877d54e9 567static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
c6918296 568 const UnitStatusMessageFormats *format_table;
877d54e9
LP
569
570 assert(u);
571 assert(t >= 0);
572 assert(t < _JOB_TYPE_MAX);
c6918296
MS
573
574 format_table = &UNIT_VTABLE(u)->status_message_formats;
575 if (!format_table)
877d54e9
LP
576 return NULL;
577
578 if (t == JOB_START)
579 return format_table->finished_start_job[result];
580 else if (t == JOB_STOP || t == JOB_RESTART)
581 return format_table->finished_stop_job[result];
582
583 return NULL;
584}
e02cd6f7 585
877d54e9
LP
586static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
587 const char *format;
588
589 assert(u);
590 assert(t >= 0);
591 assert(t < _JOB_TYPE_MAX);
592
593 format = job_get_status_message_format(u, t, result);
594 if (format)
595 return format;
596
597 /* Return generic strings */
e02cd6f7 598 if (t == JOB_START) {
877d54e9
LP
599 if (result == JOB_DONE)
600 return "Started %s.";
601 else if (result == JOB_FAILED)
602 return "Failed to start %s.";
603 else if (result == JOB_DEPENDENCY)
604 return "Dependency failed for %s.";
605 else if (result == JOB_TIMEOUT)
606 return "Timed out starting %s.";
607 } else if (t == JOB_STOP || t == JOB_RESTART) {
608 if (result == JOB_DONE)
609 return "Stopped %s.";
610 else if (result == JOB_FAILED)
611 return "Stopped (with error) %s.";
612 else if (result == JOB_TIMEOUT)
613 return "Timed out stoppping %s.";
614 } else if (t == JOB_RELOAD) {
615 if (result == JOB_DONE)
616 return "Reloaded %s.";
617 else if (result == JOB_FAILED)
618 return "Reload failed for %s.";
619 else if (result == JOB_TIMEOUT)
620 return "Timed out reloading %s.";
621 }
622
623 return NULL;
624}
625
626static void job_print_status_message(Unit *u, JobType t, JobResult result) {
627 const char *format;
e02cd6f7 628
877d54e9
LP
629 assert(u);
630 assert(t >= 0);
631 assert(t < _JOB_TYPE_MAX);
632
633 if (t == JOB_START) {
634 format = job_get_status_message_format(u, t, result);
c6918296
MS
635 if (!format)
636 return;
637
e02cd6f7
LP
638 switch (result) {
639
640 case JOB_DONE:
69120666 641 if (u->condition_result)
c6918296 642 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
643 break;
644
645 case JOB_FAILED:
c6918296 646 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
877d54e9 647 unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
e02cd6f7
LP
648 break;
649
650 case JOB_DEPENDENCY:
c6918296 651 unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
652 break;
653
654 case JOB_TIMEOUT:
c6918296 655 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
656 break;
657
658 default:
659 ;
660 }
661
1f136e7a 662 } else if (t == JOB_STOP || t == JOB_RESTART) {
e02cd6f7 663
877d54e9 664 format = job_get_status_message_format(u, t, result);
c6918296
MS
665 if (!format)
666 return;
667
e02cd6f7
LP
668 switch (result) {
669
670 case JOB_TIMEOUT:
c6918296 671 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
672 break;
673
674 case JOB_DONE:
675 case JOB_FAILED:
c6918296 676 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
677 break;
678
679 default:
680 ;
681 }
7cf82e0b
MS
682
683 } else if (t == JOB_VERIFY_ACTIVE) {
684
685 /* When verify-active detects the unit is inactive, report it.
686 * Most likely a DEPEND warning from a requisiting unit will
687 * occur next and it's nice to see what was requisited. */
688 if (result == JOB_SKIPPED)
689 unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.", unit_description(u));
e02cd6f7
LP
690 }
691}
692
877d54e9
LP
693#pragma GCC diagnostic push
694#pragma GCC diagnostic ignored "-Wformat-nonliteral"
695static void job_log_status_message(Unit *u, JobType t, JobResult result) {
696 const char *format;
697 char buf[LINE_MAX];
698
699 assert(u);
700 assert(t >= 0);
701 assert(t < _JOB_TYPE_MAX);
702
81270860
LP
703 /* Skip this if it goes to the console. since we already print
704 * to the console anyway... */
705
706 if (log_on_console())
707 return;
708
877d54e9
LP
709 format = job_get_status_message_format_try_harder(u, t, result);
710 if (!format)
711 return;
712
713 snprintf(buf, sizeof(buf), format, unit_description(u));
714 char_array_0(buf);
715
716 if (t == JOB_START) {
717 sd_id128_t mid;
718
719 mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
bbc9006e
MT
720 log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
721 u->id,
1ca6783f 722 MESSAGE_ID(mid),
877d54e9
LP
723 "RESULT=%s", job_result_to_string(result),
724 "MESSAGE=%s", buf,
725 NULL);
726
727 } else if (t == JOB_STOP)
bbc9006e
MT
728 log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
729 u->id,
1ca6783f 730 MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
877d54e9
LP
731 "RESULT=%s", job_result_to_string(result),
732 "MESSAGE=%s", buf,
733 NULL);
734
735 else if (t == JOB_RELOAD)
bbc9006e
MT
736 log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
737 u->id,
1ca6783f 738 MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
877d54e9
LP
739 "RESULT=%s", job_result_to_string(result),
740 "MESSAGE=%s", buf,
741 NULL);
742}
743#pragma GCC diagnostic pop
744
5273510e 745int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
87f0e418
LP
746 Unit *u;
747 Unit *other;
b866264a 748 JobType t;
034c6ed7 749 Iterator i;
5cb5a6ff
LP
750
751 assert(j);
ac1135be 752 assert(j->installed);
e0209d83 753 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
5cb5a6ff 754
c6918296
MS
755 u = j->unit;
756 t = j->type;
757
758 j->result = result;
759
66870f90
ZJS
760 log_debug_unit(u->id, "Job %s/%s finished, result=%s",
761 u->id, job_type_to_string(t), job_result_to_string(result));
c6918296
MS
762
763 job_print_status_message(u, t, result);
877d54e9 764 job_log_status_message(u, t, result);
c6918296 765
c1e1601e 766 job_add_to_dbus_queue(j);
f50e0a01 767
034c6ed7 768 /* Patch restart jobs so that they become normal start jobs */
c6918296 769 if (result == JOB_DONE && t == JOB_RESTART) {
f50e0a01 770
bbd1a837 771 job_change_type(j, JOB_START);
9c2d9caa 772 j->state = JOB_WAITING;
cc42e081
LP
773
774 job_add_to_run_queue(j);
57981b98 775
57981b98 776 goto finish;
5cb5a6ff
LP
777 }
778
5d44db4a 779 if (result == JOB_FAILED)
76bf48b7
LP
780 j->manager->n_failed_jobs ++;
781
97e7d748 782 job_uninstall(j);
5cb5a6ff
LP
783 job_free(j);
784
785 /* Fail depending jobs on failure */
5273510e 786 if (result != JOB_DONE && recursive) {
5cb5a6ff
LP
787
788 if (t == JOB_START ||
e0209d83 789 t == JOB_VERIFY_ACTIVE) {
5cb5a6ff 790
ac155bb8
MS
791 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
792 if (other->job &&
793 (other->job->type == JOB_START ||
e0209d83 794 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 795 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
5cb5a6ff 796
ac155bb8
MS
797 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
798 if (other->job &&
799 (other->job->type == JOB_START ||
e0209d83 800 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 801 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
e6a3ff95 802
ac155bb8
MS
803 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
804 if (other->job &&
805 !other->job->override &&
806 (other->job->type == JOB_START ||
e0209d83 807 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 808 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
5cb5a6ff
LP
809
810 } else if (t == JOB_STOP) {
811
ac155bb8
MS
812 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
813 if (other->job &&
814 (other->job->type == JOB_START ||
e0209d83 815 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 816 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
5cb5a6ff
LP
817 }
818 }
819
c0daa706 820 /* Trigger OnFailure dependencies that are not generated by
66870f90 821 * the unit itself. We don't treat JOB_CANCELED as failure in
c0daa706
LP
822 * this context. And JOB_FAILURE is already handled by the
823 * unit itself. */
222ae6a8 824 if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
bbc9006e
MT
825 log_struct_unit(LOG_NOTICE,
826 u->id,
66870f90 827 "JOB_TYPE=%s", job_type_to_string(t),
38c888a4 828 "JOB_RESULT=%s", job_result_to_string(result),
66870f90 829 "Job %s/%s failed with result '%s'.",
ac155bb8 830 u->id,
222ae6a8 831 job_type_to_string(t),
66870f90
ZJS
832 job_result_to_string(result),
833 NULL);
222ae6a8 834
c0daa706 835 unit_trigger_on_failure(u);
222ae6a8 836 }
c0daa706 837
57981b98 838finish:
5cb5a6ff 839 /* Try to start the next jobs that can be started */
ac155bb8
MS
840 SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
841 if (other->job)
842 job_add_to_run_queue(other->job);
843 SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
844 if (other->job)
845 job_add_to_run_queue(other->job);
5cb5a6ff 846
ac155bb8 847 manager_check_finished(u->manager);
b0c918b9 848
5273510e 849 return 0;
5cb5a6ff 850}
034c6ed7 851
faf919f1
LP
852int job_start_timer(Job *j) {
853 struct itimerspec its;
854 struct epoll_event ev;
855 int fd, r;
856 assert(j);
857
ac155bb8 858 if (j->unit->job_timeout <= 0 ||
faf919f1
LP
859 j->timer_watch.type == WATCH_JOB_TIMER)
860 return 0;
861
862 assert(j->timer_watch.type == WATCH_INVALID);
863
864 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
865 r = -errno;
866 goto fail;
867 }
868
869 zero(its);
ac155bb8 870 timespec_store(&its.it_value, j->unit->job_timeout);
faf919f1
LP
871
872 if (timerfd_settime(fd, 0, &its, NULL) < 0) {
873 r = -errno;
874 goto fail;
875 }
876
877 zero(ev);
878 ev.data.ptr = &j->timer_watch;
879 ev.events = EPOLLIN;
880
881 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
882 r = -errno;
883 goto fail;
884 }
885
886 j->timer_watch.type = WATCH_JOB_TIMER;
887 j->timer_watch.fd = fd;
888 j->timer_watch.data.job = j;
889
890 return 0;
891
892fail:
893 if (fd >= 0)
894 close_nointr_nofail(fd);
895
896 return r;
897}
898
c1e1601e 899void job_add_to_run_queue(Job *j) {
034c6ed7 900 assert(j);
ac1135be 901 assert(j->installed);
034c6ed7
LP
902
903 if (j->in_run_queue)
904 return;
905
906 LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
907 j->in_run_queue = true;
908}
94f04347 909
c1e1601e
LP
910void job_add_to_dbus_queue(Job *j) {
911 assert(j);
912 assert(j->installed);
913
914 if (j->in_dbus_queue)
915 return;
916
a567261a
LP
917 /* We don't check if anybody is subscribed here, since this
918 * job might just have been created and not yet assigned to a
919 * connection/client. */
94b6dfa2 920
c1e1601e
LP
921 LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
922 j->in_dbus_queue = true;
923}
924
ea430986
LP
925char *job_dbus_path(Job *j) {
926 char *p;
927
928 assert(j);
929
930 if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
931 return NULL;
932
933 return p;
934}
935
faf919f1
LP
936void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
937 assert(j);
938 assert(w == &j->timer_watch);
939
66870f90
ZJS
940 log_warning_unit(j->unit->id, "Job %s/%s timed out.",
941 j->unit->id, job_type_to_string(j->type));
5273510e 942 job_finish_and_invalidate(j, JOB_TIMEOUT, true);
faf919f1
LP
943}
944
39a18c60
MS
945int job_serialize(Job *j, FILE *f, FDSet *fds) {
946 fprintf(f, "job-id=%u\n", j->id);
947 fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
948 fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
949 fprintf(f, "job-override=%s\n", yes_no(j->override));
950 fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
951 fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
952 /* Cannot save bus clients. Just note the fact that we're losing
953 * them. job_send_message() will fallback to broadcasting. */
954 fprintf(f, "job-forgot-bus-clients=%s\n",
955 yes_no(j->forgot_bus_clients || j->bus_client_list));
956 if (j->timer_watch.type == WATCH_JOB_TIMER) {
957 int copy = fdset_put_dup(fds, j->timer_watch.fd);
958 if (copy < 0)
959 return copy;
960 fprintf(f, "job-timer-watch-fd=%d\n", copy);
961 }
962
963 /* End marker */
964 fputc('\n', f);
965 return 0;
966}
967
968int job_deserialize(Job *j, FILE *f, FDSet *fds) {
969 for (;;) {
970 char line[LINE_MAX], *l, *v;
971 size_t k;
972
973 if (!fgets(line, sizeof(line), f)) {
974 if (feof(f))
975 return 0;
976 return -errno;
977 }
978
979 char_array_0(line);
980 l = strstrip(line);
981
982 /* End marker */
983 if (l[0] == 0)
984 return 0;
985
986 k = strcspn(l, "=");
987
988 if (l[k] == '=') {
989 l[k] = 0;
990 v = l+k+1;
991 } else
992 v = l+k;
993
994 if (streq(l, "job-id")) {
995 if (safe_atou32(v, &j->id) < 0)
996 log_debug("Failed to parse job id value %s", v);
997 } else if (streq(l, "job-type")) {
998 JobType t = job_type_from_string(v);
999 if (t < 0)
1000 log_debug("Failed to parse job type %s", v);
e0209d83
MS
1001 else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
1002 log_debug("Cannot deserialize job of type %s", v);
39a18c60
MS
1003 else
1004 j->type = t;
1005 } else if (streq(l, "job-state")) {
1006 JobState s = job_state_from_string(v);
1007 if (s < 0)
1008 log_debug("Failed to parse job state %s", v);
1009 else
1010 j->state = s;
1011 } else if (streq(l, "job-override")) {
1012 int b = parse_boolean(v);
1013 if (b < 0)
1014 log_debug("Failed to parse job override flag %s", v);
1015 else
1016 j->override = j->override || b;
1017 } else if (streq(l, "job-sent-dbus-new-signal")) {
1018 int b = parse_boolean(v);
1019 if (b < 0)
1020 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
1021 else
1022 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
1023 } else if (streq(l, "job-ignore-order")) {
1024 int b = parse_boolean(v);
1025 if (b < 0)
1026 log_debug("Failed to parse job ignore_order flag %s", v);
1027 else
1028 j->ignore_order = j->ignore_order || b;
1029 } else if (streq(l, "job-forgot-bus-clients")) {
1030 int b = parse_boolean(v);
1031 if (b < 0)
1032 log_debug("Failed to parse job forgot_bus_clients flag %s", v);
1033 else
1034 j->forgot_bus_clients = j->forgot_bus_clients || b;
1035 } else if (streq(l, "job-timer-watch-fd")) {
1036 int fd;
1037 if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
1038 log_debug("Failed to parse job-timer-watch-fd value %s", v);
1039 else {
1040 if (j->timer_watch.type == WATCH_JOB_TIMER)
1041 close_nointr_nofail(j->timer_watch.fd);
1042
1043 j->timer_watch.type = WATCH_JOB_TIMER;
1044 j->timer_watch.fd = fdset_remove(fds, fd);
1045 j->timer_watch.data.job = j;
1046 }
1047 }
1048 }
1049}
1050
1051int job_coldplug(Job *j) {
1052 struct epoll_event ev;
1053
1054 if (j->timer_watch.type != WATCH_JOB_TIMER)
1055 return 0;
1056
1057 zero(ev);
1058 ev.data.ptr = &j->timer_watch;
1059 ev.events = EPOLLIN;
1060
1061 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
1062 return -errno;
1063
1064 return 0;
1065}
1066
c65eb836
LP
1067void job_shutdown_magic(Job *j) {
1068 assert(j);
1069
1070 /* The shutdown target gets some special treatment here: we
1071 * tell the kernel to begin with flushing its disk caches, to
1072 * optimize shutdown time a bit. Ideally we wouldn't hardcode
1073 * this magic into PID 1. However all other processes aren't
1074 * options either since they'd exit much sooner than PID 1 and
1075 * asynchronous sync() would cause their exit to be
1076 * delayed. */
1077
1078 if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
1079 return;
1080
1081 if (j->type != JOB_START)
1082 return;
1083
1084 if (detect_container(NULL) > 0)
1085 return;
1086
1087 asynchronous_sync();
1088}
1089
94f04347
LP
1090static const char* const job_state_table[_JOB_STATE_MAX] = {
1091 [JOB_WAITING] = "waiting",
1092 [JOB_RUNNING] = "running"
1093};
1094
1095DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
1096
1097static const char* const job_type_table[_JOB_TYPE_MAX] = {
1098 [JOB_START] = "start",
1099 [JOB_VERIFY_ACTIVE] = "verify-active",
1100 [JOB_STOP] = "stop",
1101 [JOB_RELOAD] = "reload",
1102 [JOB_RELOAD_OR_START] = "reload-or-start",
1103 [JOB_RESTART] = "restart",
1104 [JOB_TRY_RESTART] = "try-restart",
e0209d83 1105 [JOB_NOP] = "nop",
94f04347
LP
1106};
1107
1108DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
b548631a
LP
1109
1110static const char* const job_mode_table[_JOB_MODE_MAX] = {
1111 [JOB_FAIL] = "fail",
c497c7a9 1112 [JOB_REPLACE] = "replace",
e67c3609 1113 [JOB_ISOLATE] = "isolate",
cebe0d41
LP
1114 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
1115 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
b548631a
LP
1116};
1117
1118DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
5d44db4a
LP
1119
1120static const char* const job_result_table[_JOB_RESULT_MAX] = {
1121 [JOB_DONE] = "done",
1122 [JOB_CANCELED] = "canceled",
1123 [JOB_TIMEOUT] = "timeout",
1124 [JOB_FAILED] = "failed",
d68201e9
LP
1125 [JOB_DEPENDENCY] = "dependency",
1126 [JOB_SKIPPED] = "skipped"
5d44db4a
LP
1127};
1128
1129DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);