]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/job.c
journal: new logging macros to include UNIT=
[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"
60918275 37
97e6a119
MS
38JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
39 JobBusClient *cl;
40 size_t name_len;
41
42 name_len = strlen(name);
43 cl = malloc0(sizeof(JobBusClient) + name_len + 1);
44 if (!cl)
45 return NULL;
46
47 cl->bus = connection;
48 memcpy(cl->name, name, name_len + 1);
49 return cl;
50}
51
39a18c60 52Job* job_new_raw(Unit *unit) {
60918275
LP
53 Job *j;
54
39a18c60
MS
55 /* used for deserialization */
56
87f0e418 57 assert(unit);
60918275 58
39a18c60
MS
59 j = new0(Job, 1);
60 if (!j)
60918275
LP
61 return NULL;
62
668ad332 63 j->manager = unit->manager;
87f0e418 64 j->unit = unit;
e0209d83 65 j->type = _JOB_TYPE_INVALID;
faf919f1
LP
66 j->timer_watch.type = WATCH_INVALID;
67
39a18c60
MS
68 return j;
69}
70
71Job* job_new(Unit *unit, JobType type) {
72 Job *j;
73
74 assert(type < _JOB_TYPE_MAX);
75
76 j = job_new_raw(unit);
77 if (!j)
78 return NULL;
79
80 j->id = j->manager->current_job_id++;
81 j->type = type;
82
e5b5ae50 83 /* We don't link it here, that's what job_dependency() is for */
60918275
LP
84
85 return j;
86}
87
97e7d748 88void job_free(Job *j) {
97e6a119
MS
89 JobBusClient *cl;
90
97e7d748
MS
91 assert(j);
92 assert(!j->installed);
02a3bcc6
MS
93 assert(!j->transaction_prev);
94 assert(!j->transaction_next);
95 assert(!j->subject_list);
96 assert(!j->object_list);
60918275 97
c1e1601e
LP
98 if (j->in_run_queue)
99 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
100
101 if (j->in_dbus_queue)
102 LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
103
faf919f1
LP
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);
108
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);
111 }
112
97e6a119
MS
113 while ((cl = j->bus_client_list)) {
114 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
115 free(cl);
116 }
60918275
LP
117 free(j);
118}
a66d02c3 119
05d576f1 120void job_uninstall(Job *j) {
e0209d83
MS
121 Job **pj;
122
05d576f1 123 assert(j->installed);
e0209d83
MS
124
125 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
126 assert(*pj == j);
127
05d576f1
MS
128 /* Detach from next 'bigger' objects */
129
39a18c60
MS
130 /* daemon-reload should be transparent to job observers */
131 if (j->manager->n_reloading <= 0)
132 bus_job_send_removed_signal(j);
05d576f1 133
e0209d83
MS
134 *pj = NULL;
135
d6a093d0 136 unit_add_to_gc_queue(j->unit);
05d576f1
MS
137
138 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
139 j->installed = false;
140}
141
656bbffc
MS
142static bool job_type_allows_late_merge(JobType t) {
143 /* Tells whether it is OK to merge a job of type 't' with an already
144 * running job.
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. */
e0209d83 156 return t != JOB_RELOAD;
656bbffc
MS
157}
158
159static void job_merge_into_installed(Job *j, Job *other) {
160 assert(j->installed);
161 assert(j->unit == other->unit);
162
e0209d83
MS
163 if (j->type != JOB_NOP)
164 job_type_merge_and_collapse(&j->type, other->type, j->unit);
165 else
166 assert(other->type == JOB_NOP);
656bbffc
MS
167
168 j->override = j->override || other->override;
169}
170
171Job* job_install(Job *j) {
e0209d83
MS
172 Job **pj;
173 Job *uj;
05d576f1 174
656bbffc 175 assert(!j->installed);
e0209d83
MS
176 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
177
178 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
179 uj = *pj;
656bbffc 180
05d576f1 181 if (uj) {
e0209d83 182 if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
1abc85b8 183 job_finish_and_invalidate(uj, JOB_CANCELED, false);
656bbffc
MS
184 else {
185 /* not conflicting, i.e. mergeable */
186
e0209d83 187 if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
656bbffc
MS
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);
192 return uj;
193 } else {
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;
202 return uj;
203 }
204 }
05d576f1
MS
205 }
206
656bbffc 207 /* Install the job */
e0209d83 208 *pj = j;
05d576f1
MS
209 j->installed = true;
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);
656bbffc 212 return j;
05d576f1
MS
213}
214
e0209d83
MS
215int job_install_deserialized(Job *j) {
216 Job **pj;
217
39a18c60
MS
218 assert(!j->installed);
219
e0209d83
MS
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)));
222 return -EINVAL;
223 }
224
225 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
226
227 if (*pj) {
39a18c60 228 log_debug("Unit %s already has a job installed. Not installing deserialized job.", j->unit->id);
e0209d83 229 return -EEXIST;
39a18c60 230 }
e0209d83 231 *pj = j;
39a18c60
MS
232 j->installed = true;
233 log_debug("Reinstalled deserialized job %s/%s as %u", j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
e0209d83 234 return 0;
39a18c60
MS
235}
236
1da4264f 237JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
e5b5ae50
LP
238 JobDependency *l;
239
240 assert(object);
241
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
35b8ca3a 245 * explicitly asked for) is the requester. */
e5b5ae50 246
ceed3570 247 if (!(l = new0(JobDependency, 1)))
e5b5ae50
LP
248 return NULL;
249
250 l->subject = subject;
251 l->object = object;
252 l->matters = matters;
69dd2852 253 l->conflicts = conflicts;
e5b5ae50 254
44d8db9e
LP
255 if (subject)
256 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
e5b5ae50 257
44d8db9e 258 LIST_PREPEND(JobDependency, object, object->object_list, l);
e5b5ae50
LP
259
260 return l;
261}
262
1da4264f 263void job_dependency_free(JobDependency *l) {
e5b5ae50
LP
264 assert(l);
265
44d8db9e
LP
266 if (l->subject)
267 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
e5b5ae50 268
44d8db9e 269 LIST_REMOVE(JobDependency, object, l->object->object_list, l);
e5b5ae50
LP
270
271 free(l);
272}
273
1ffba6fe 274void job_dump(Job *j, FILE*f, const char *prefix) {
a66d02c3
LP
275 assert(j);
276 assert(f);
277
9eb63b3c
LP
278 if (!prefix)
279 prefix = "";
280
ceed3570 281 fprintf(f,
40d50879
LP
282 "%s-> Job %u:\n"
283 "%s\tAction: %s -> %s\n"
5cb5a6ff
LP
284 "%s\tState: %s\n"
285 "%s\tForced: %s\n",
ceed3570 286 prefix, j->id,
ac155bb8 287 prefix, j->unit->id, job_type_to_string(j->type),
94f04347 288 prefix, job_state_to_string(j->state),
9e2f7c11 289 prefix, yes_no(j->override));
a66d02c3 290}
e5b5ae50 291
348e27fe
MS
292/*
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.
296 *
e0209d83
MS
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:
300 *
348e27fe
MS
301 * Merging is associative! A merged with B merged with C is the same as
302 * A merged with C merged with B.
303 *
304 * Mergeability is transitive! If A can be merged with B and B with C then
305 * A also with C.
306 *
307 * Also, if A merged with B cannot be merged with C, then either A or B cannot
308 * be merged with C either.
309 */
310static const JobType job_merging_table[] = {
e0209d83
MS
311/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
312/*********************************************************************************/
348e27fe
MS
313/*JOB_START */
314/*JOB_VERIFY_ACTIVE */ JOB_START,
315/*JOB_STOP */ -1, -1,
316/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
e0209d83 317/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
348e27fe
MS
318};
319
320JobType job_type_lookup_merge(JobType a, JobType b) {
e0209d83
MS
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);
1ffba6fe
LP
324
325 if (a == b)
348e27fe 326 return a;
1ffba6fe 327
348e27fe
MS
328 if (a < b) {
329 JobType tmp = a;
330 a = b;
331 b = tmp;
1ffba6fe 332 }
e094e853 333
348e27fe 334 return job_merging_table[(a - 1) * a / 2 + b];
e094e853 335}
cd2dbd7d 336
593fbdd2
LP
337bool job_type_is_redundant(JobType a, UnitActiveState b) {
338 switch (a) {
339
340 case JOB_START:
341 return
342 b == UNIT_ACTIVE ||
032ff4af 343 b == UNIT_RELOADING;
593fbdd2
LP
344
345 case JOB_STOP:
346 return
6124958c 347 b == UNIT_INACTIVE ||
fdf20a31 348 b == UNIT_FAILED;
593fbdd2
LP
349
350 case JOB_VERIFY_ACTIVE:
351 return
352 b == UNIT_ACTIVE ||
032ff4af 353 b == UNIT_RELOADING;
593fbdd2
LP
354
355 case JOB_RELOAD:
356 return
032ff4af 357 b == UNIT_RELOADING;
593fbdd2 358
593fbdd2
LP
359 case JOB_RESTART:
360 return
361 b == UNIT_ACTIVATING;
362
e0209d83
MS
363 default:
364 assert_not_reached("Invalid job type");
365 }
366}
367
368void job_type_collapse(JobType *t, Unit *u) {
369 UnitActiveState s;
370
371 switch (*t) {
372
593fbdd2 373 case JOB_TRY_RESTART:
e0209d83
MS
374 s = unit_active_state(u);
375 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
376 *t = JOB_NOP;
377 else
378 *t = JOB_RESTART;
379 break;
380
381 case JOB_RELOAD_OR_START:
382 s = unit_active_state(u);
383 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
384 *t = JOB_START;
385 else
386 *t = JOB_RELOAD;
387 break;
593fbdd2
LP
388
389 default:
e0209d83 390 ;
593fbdd2
LP
391 }
392}
393
e0209d83
MS
394int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
395 JobType t = job_type_lookup_merge(*a, b);
396 if (t < 0)
397 return -EEXIST;
398 *a = t;
399 job_type_collapse(a, u);
400 return 0;
401}
402
5cb5a6ff 403bool job_is_runnable(Job *j) {
034c6ed7 404 Iterator i;
87f0e418 405 Unit *other;
5cb5a6ff
LP
406
407 assert(j);
ac1135be 408 assert(j->installed);
5cb5a6ff 409
87f0e418 410 /* Checks whether there is any job running for the units this
5cb5a6ff 411 * job needs to be running after (in the case of a 'positive'
e67c3609
LP
412 * job type) or before (in the case of a 'negative' job
413 * type. */
414
415 /* First check if there is an override */
cebe0d41 416 if (j->ignore_order)
e67c3609 417 return true;
5cb5a6ff 418
e0209d83
MS
419 if (j->type == JOB_NOP)
420 return true;
421
5cb5a6ff
LP
422 if (j->type == JOB_START ||
423 j->type == JOB_VERIFY_ACTIVE ||
e0209d83 424 j->type == JOB_RELOAD) {
5cb5a6ff
LP
425
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. */
430
ac155bb8
MS
431 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
432 if (other->job)
5cb5a6ff
LP
433 return false;
434 }
435
436 /* Also, if something else is being stopped and we should
437 * change state after it, then lets wait. */
438
ac155bb8
MS
439 SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
440 if (other->job &&
441 (other->job->type == JOB_STOP ||
e0209d83 442 other->job->type == JOB_RESTART))
5cb5a6ff
LP
443 return false;
444
445 /* This means that for a service a and a service b where b
446 * shall be started after a:
447 *
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
452 *
453 * This has the side effect that restarts are properly
454 * synchronized too. */
455
456 return true;
457}
458
bbd1a837
MS
459static 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));
463
464 j->type = newtype;
465}
466
5cb5a6ff
LP
467int job_run_and_invalidate(Job *j) {
468 int r;
2cf19a7a
LP
469 uint32_t id;
470 Manager *m;
ac1135be 471
5cb5a6ff 472 assert(j);
ac1135be 473 assert(j->installed);
e0209d83 474 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
66aa6f7f 475 assert(j->in_run_queue);
5cb5a6ff 476
66aa6f7f
MS
477 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
478 j->in_run_queue = false;
5cb5a6ff
LP
479
480 if (j->state != JOB_WAITING)
481 return 0;
482
034c6ed7
LP
483 if (!job_is_runnable(j))
484 return -EAGAIN;
485
83c60c9f 486 j->state = JOB_RUNNING;
c1e1601e 487 job_add_to_dbus_queue(j);
83c60c9f 488
2cf19a7a
LP
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
493 * valid. */
494 id = j->id;
495 m = j->manager;
496
5cb5a6ff
LP
497 switch (j->type) {
498
499 case JOB_START:
87f0e418 500 r = unit_start(j->unit);
57339f47 501
dd17d388 502 /* If this unit cannot be started, then simply wait */
5cb5a6ff
LP
503 if (r == -EBADR)
504 r = 0;
505 break;
506
507 case JOB_VERIFY_ACTIVE: {
87f0e418
LP
508 UnitActiveState t = unit_active_state(j->unit);
509 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
5cb5a6ff 510 r = -EALREADY;
87f0e418 511 else if (t == UNIT_ACTIVATING)
5cb5a6ff
LP
512 r = -EAGAIN;
513 else
514 r = -ENOEXEC;
515 break;
516 }
517
518 case JOB_STOP:
dd17d388 519 case JOB_RESTART:
87f0e418 520 r = unit_stop(j->unit);
57339f47 521
dd17d388 522 /* If this unit cannot stopped, then simply wait. */
57339f47
LP
523 if (r == -EBADR)
524 r = 0;
5cb5a6ff
LP
525 break;
526
527 case JOB_RELOAD:
87f0e418 528 r = unit_reload(j->unit);
5cb5a6ff
LP
529 break;
530
e0209d83
MS
531 case JOB_NOP:
532 r = -EALREADY;
533 break;
534
5cb5a6ff 535 default:
44d8db9e 536 assert_not_reached("Unknown job type");
5cb5a6ff
LP
537 }
538
e0209d83
MS
539 j = manager_get_job(m, id);
540 if (j) {
2cf19a7a 541 if (r == -EALREADY)
5273510e 542 r = job_finish_and_invalidate(j, JOB_DONE, true);
d68201e9 543 else if (r == -ENOEXEC)
5273510e 544 r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
2cf19a7a
LP
545 else if (r == -EAGAIN)
546 j->state = JOB_WAITING;
547 else if (r < 0)
5273510e 548 r = job_finish_and_invalidate(j, JOB_FAILED, true);
2cf19a7a 549 }
5cb5a6ff
LP
550
551 return r;
552}
553
877d54e9 554static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
c6918296 555 const UnitStatusMessageFormats *format_table;
877d54e9
LP
556
557 assert(u);
558 assert(t >= 0);
559 assert(t < _JOB_TYPE_MAX);
c6918296
MS
560
561 format_table = &UNIT_VTABLE(u)->status_message_formats;
562 if (!format_table)
877d54e9
LP
563 return NULL;
564
565 if (t == JOB_START)
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];
569
570 return NULL;
571}
e02cd6f7 572
877d54e9
LP
573static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
574 const char *format;
575
576 assert(u);
577 assert(t >= 0);
578 assert(t < _JOB_TYPE_MAX);
579
580 format = job_get_status_message_format(u, t, result);
581 if (format)
582 return format;
583
584 /* Return generic strings */
e02cd6f7 585 if (t == JOB_START) {
877d54e9
LP
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.";
608 }
609
610 return NULL;
611}
612
613static void job_print_status_message(Unit *u, JobType t, JobResult result) {
614 const char *format;
e02cd6f7 615
877d54e9
LP
616 assert(u);
617 assert(t >= 0);
618 assert(t < _JOB_TYPE_MAX);
619
620 if (t == JOB_START) {
621 format = job_get_status_message_format(u, t, result);
c6918296
MS
622 if (!format)
623 return;
624
e02cd6f7
LP
625 switch (result) {
626
627 case JOB_DONE:
69120666 628 if (u->condition_result)
c6918296 629 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
630 break;
631
632 case JOB_FAILED:
c6918296 633 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
877d54e9 634 unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
e02cd6f7
LP
635 break;
636
637 case JOB_DEPENDENCY:
c6918296 638 unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
639 break;
640
641 case JOB_TIMEOUT:
c6918296 642 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
643 break;
644
645 default:
646 ;
647 }
648
1f136e7a 649 } else if (t == JOB_STOP || t == JOB_RESTART) {
e02cd6f7 650
877d54e9 651 format = job_get_status_message_format(u, t, result);
c6918296
MS
652 if (!format)
653 return;
654
e02cd6f7
LP
655 switch (result) {
656
657 case JOB_TIMEOUT:
c6918296 658 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
659 break;
660
661 case JOB_DONE:
662 case JOB_FAILED:
c6918296 663 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
664 break;
665
666 default:
667 ;
668 }
7cf82e0b
MS
669
670 } else if (t == JOB_VERIFY_ACTIVE) {
671
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));
e02cd6f7
LP
677 }
678}
679
877d54e9
LP
680#pragma GCC diagnostic push
681#pragma GCC diagnostic ignored "-Wformat-nonliteral"
682static void job_log_status_message(Unit *u, JobType t, JobResult result) {
683 const char *format;
684 char buf[LINE_MAX];
685
686 assert(u);
687 assert(t >= 0);
688 assert(t < _JOB_TYPE_MAX);
689
81270860
LP
690 /* Skip this if it goes to the console. since we already print
691 * to the console anyway... */
692
693 if (log_on_console())
694 return;
695
877d54e9
LP
696 format = job_get_status_message_format_try_harder(u, t, result);
697 if (!format)
698 return;
699
700 snprintf(buf, sizeof(buf), format, unit_description(u));
701 char_array_0(buf);
702
703 if (t == JOB_START) {
704 sd_id128_t mid;
705
706 mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
707 log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
1ca6783f 708 MESSAGE_ID(mid),
877d54e9
LP
709 "UNIT=%s", u->id,
710 "RESULT=%s", job_result_to_string(result),
711 "MESSAGE=%s", buf,
712 NULL);
713
714 } else if (t == JOB_STOP)
715 log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
1ca6783f 716 MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
877d54e9
LP
717 "UNIT=%s", u->id,
718 "RESULT=%s", job_result_to_string(result),
719 "MESSAGE=%s", buf,
720 NULL);
721
722 else if (t == JOB_RELOAD)
723 log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
1ca6783f 724 MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
877d54e9
LP
725 "UNIT=%s", u->id,
726 "RESULT=%s", job_result_to_string(result),
727 "MESSAGE=%s", buf,
728 NULL);
729}
730#pragma GCC diagnostic pop
731
5273510e 732int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
87f0e418
LP
733 Unit *u;
734 Unit *other;
b866264a 735 JobType t;
034c6ed7 736 Iterator i;
5cb5a6ff
LP
737
738 assert(j);
ac1135be 739 assert(j->installed);
e0209d83 740 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
5cb5a6ff 741
c6918296
MS
742 u = j->unit;
743 t = j->type;
744
745 j->result = result;
746
747 log_debug("Job %s/%s finished, result=%s", u->id, job_type_to_string(t), job_result_to_string(result));
748
749 job_print_status_message(u, t, result);
877d54e9 750 job_log_status_message(u, t, result);
c6918296 751
c1e1601e 752 job_add_to_dbus_queue(j);
f50e0a01 753
034c6ed7 754 /* Patch restart jobs so that they become normal start jobs */
c6918296 755 if (result == JOB_DONE && t == JOB_RESTART) {
f50e0a01 756
bbd1a837 757 job_change_type(j, JOB_START);
9c2d9caa 758 j->state = JOB_WAITING;
cc42e081
LP
759
760 job_add_to_run_queue(j);
57981b98 761
57981b98 762 goto finish;
5cb5a6ff
LP
763 }
764
5d44db4a 765 if (result == JOB_FAILED)
76bf48b7
LP
766 j->manager->n_failed_jobs ++;
767
97e7d748 768 job_uninstall(j);
5cb5a6ff
LP
769 job_free(j);
770
771 /* Fail depending jobs on failure */
5273510e 772 if (result != JOB_DONE && recursive) {
5cb5a6ff
LP
773
774 if (t == JOB_START ||
e0209d83 775 t == JOB_VERIFY_ACTIVE) {
5cb5a6ff 776
ac155bb8
MS
777 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
778 if (other->job &&
779 (other->job->type == JOB_START ||
e0209d83 780 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 781 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
5cb5a6ff 782
ac155bb8
MS
783 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
784 if (other->job &&
785 (other->job->type == JOB_START ||
e0209d83 786 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 787 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
e6a3ff95 788
ac155bb8
MS
789 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
790 if (other->job &&
791 !other->job->override &&
792 (other->job->type == JOB_START ||
e0209d83 793 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 794 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
5cb5a6ff
LP
795
796 } else if (t == JOB_STOP) {
797
ac155bb8
MS
798 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
799 if (other->job &&
800 (other->job->type == JOB_START ||
e0209d83 801 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 802 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
5cb5a6ff
LP
803 }
804 }
805
c0daa706
LP
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
809 * unit itself. */
222ae6a8
LP
810 if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
811 log_notice("Job %s/%s failed with result '%s'.",
ac155bb8 812 u->id,
222ae6a8
LP
813 job_type_to_string(t),
814 job_result_to_string(result));
815
c0daa706 816 unit_trigger_on_failure(u);
222ae6a8 817 }
c0daa706 818
57981b98 819finish:
5cb5a6ff 820 /* Try to start the next jobs that can be started */
ac155bb8
MS
821 SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
822 if (other->job)
823 job_add_to_run_queue(other->job);
824 SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
825 if (other->job)
826 job_add_to_run_queue(other->job);
5cb5a6ff 827
ac155bb8 828 manager_check_finished(u->manager);
b0c918b9 829
5273510e 830 return 0;
5cb5a6ff 831}
034c6ed7 832
faf919f1
LP
833int job_start_timer(Job *j) {
834 struct itimerspec its;
835 struct epoll_event ev;
836 int fd, r;
837 assert(j);
838
ac155bb8 839 if (j->unit->job_timeout <= 0 ||
faf919f1
LP
840 j->timer_watch.type == WATCH_JOB_TIMER)
841 return 0;
842
843 assert(j->timer_watch.type == WATCH_INVALID);
844
845 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
846 r = -errno;
847 goto fail;
848 }
849
850 zero(its);
ac155bb8 851 timespec_store(&its.it_value, j->unit->job_timeout);
faf919f1
LP
852
853 if (timerfd_settime(fd, 0, &its, NULL) < 0) {
854 r = -errno;
855 goto fail;
856 }
857
858 zero(ev);
859 ev.data.ptr = &j->timer_watch;
860 ev.events = EPOLLIN;
861
862 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
863 r = -errno;
864 goto fail;
865 }
866
867 j->timer_watch.type = WATCH_JOB_TIMER;
868 j->timer_watch.fd = fd;
869 j->timer_watch.data.job = j;
870
871 return 0;
872
873fail:
874 if (fd >= 0)
875 close_nointr_nofail(fd);
876
877 return r;
878}
879
c1e1601e 880void job_add_to_run_queue(Job *j) {
034c6ed7 881 assert(j);
ac1135be 882 assert(j->installed);
034c6ed7
LP
883
884 if (j->in_run_queue)
885 return;
886
887 LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
888 j->in_run_queue = true;
889}
94f04347 890
c1e1601e
LP
891void job_add_to_dbus_queue(Job *j) {
892 assert(j);
893 assert(j->installed);
894
895 if (j->in_dbus_queue)
896 return;
897
a567261a
LP
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. */
94b6dfa2 901
c1e1601e
LP
902 LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
903 j->in_dbus_queue = true;
904}
905
ea430986
LP
906char *job_dbus_path(Job *j) {
907 char *p;
908
909 assert(j);
910
911 if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
912 return NULL;
913
914 return p;
915}
916
faf919f1
LP
917void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
918 assert(j);
919 assert(w == &j->timer_watch);
920
ac155bb8 921 log_warning("Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
5273510e 922 job_finish_and_invalidate(j, JOB_TIMEOUT, true);
faf919f1
LP
923}
924
39a18c60
MS
925int 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);
938 if (copy < 0)
939 return copy;
940 fprintf(f, "job-timer-watch-fd=%d\n", copy);
941 }
942
943 /* End marker */
944 fputc('\n', f);
945 return 0;
946}
947
948int job_deserialize(Job *j, FILE *f, FDSet *fds) {
949 for (;;) {
950 char line[LINE_MAX], *l, *v;
951 size_t k;
952
953 if (!fgets(line, sizeof(line), f)) {
954 if (feof(f))
955 return 0;
956 return -errno;
957 }
958
959 char_array_0(line);
960 l = strstrip(line);
961
962 /* End marker */
963 if (l[0] == 0)
964 return 0;
965
966 k = strcspn(l, "=");
967
968 if (l[k] == '=') {
969 l[k] = 0;
970 v = l+k+1;
971 } else
972 v = l+k;
973
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);
979 if (t < 0)
980 log_debug("Failed to parse job type %s", v);
e0209d83
MS
981 else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
982 log_debug("Cannot deserialize job of type %s", v);
39a18c60
MS
983 else
984 j->type = t;
985 } else if (streq(l, "job-state")) {
986 JobState s = job_state_from_string(v);
987 if (s < 0)
988 log_debug("Failed to parse job state %s", v);
989 else
990 j->state = s;
991 } else if (streq(l, "job-override")) {
992 int b = parse_boolean(v);
993 if (b < 0)
994 log_debug("Failed to parse job override flag %s", v);
995 else
996 j->override = j->override || b;
997 } else if (streq(l, "job-sent-dbus-new-signal")) {
998 int b = parse_boolean(v);
999 if (b < 0)
1000 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
1001 else
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);
1005 if (b < 0)
1006 log_debug("Failed to parse job ignore_order flag %s", v);
1007 else
1008 j->ignore_order = j->ignore_order || b;
1009 } else if (streq(l, "job-forgot-bus-clients")) {
1010 int b = parse_boolean(v);
1011 if (b < 0)
1012 log_debug("Failed to parse job forgot_bus_clients flag %s", v);
1013 else
1014 j->forgot_bus_clients = j->forgot_bus_clients || b;
1015 } else if (streq(l, "job-timer-watch-fd")) {
1016 int 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);
1019 else {
1020 if (j->timer_watch.type == WATCH_JOB_TIMER)
1021 close_nointr_nofail(j->timer_watch.fd);
1022
1023 j->timer_watch.type = WATCH_JOB_TIMER;
1024 j->timer_watch.fd = fdset_remove(fds, fd);
1025 j->timer_watch.data.job = j;
1026 }
1027 }
1028 }
1029}
1030
1031int job_coldplug(Job *j) {
1032 struct epoll_event ev;
1033
1034 if (j->timer_watch.type != WATCH_JOB_TIMER)
1035 return 0;
1036
1037 zero(ev);
1038 ev.data.ptr = &j->timer_watch;
1039 ev.events = EPOLLIN;
1040
1041 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
1042 return -errno;
1043
1044 return 0;
1045}
1046
94f04347
LP
1047static const char* const job_state_table[_JOB_STATE_MAX] = {
1048 [JOB_WAITING] = "waiting",
1049 [JOB_RUNNING] = "running"
1050};
1051
1052DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
1053
1054static 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",
e0209d83 1062 [JOB_NOP] = "nop",
94f04347
LP
1063};
1064
1065DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
b548631a
LP
1066
1067static const char* const job_mode_table[_JOB_MODE_MAX] = {
1068 [JOB_FAIL] = "fail",
c497c7a9 1069 [JOB_REPLACE] = "replace",
e67c3609 1070 [JOB_ISOLATE] = "isolate",
cebe0d41
LP
1071 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
1072 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
b548631a
LP
1073};
1074
1075DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
5d44db4a
LP
1076
1077static 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",
d68201e9
LP
1082 [JOB_DEPENDENCY] = "dependency",
1083 [JOB_SKIPPED] = "skipped"
5d44db4a
LP
1084};
1085
1086DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);