]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/job.c
tree-wide: remove Lennart's copyright lines
[thirdparty/systemd.git] / src / core / job.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a7334b09 2
1ffba6fe 3#include <errno.h>
60918275 4
718db961
LP
5#include "sd-id128.h"
6#include "sd-messages.h"
4f5dd394 7
b5efdb8a 8#include "alloc-util.h"
f485606b 9#include "async.h"
4f5dd394 10#include "dbus-job.h"
8f8f05a9 11#include "dbus.h"
4f5dd394 12#include "escape.h"
6bedfcbb 13#include "job.h"
4f5dd394
LP
14#include "log.h"
15#include "macro.h"
6bedfcbb 16#include "parse-util.h"
4f5dd394
LP
17#include "set.h"
18#include "special.h"
d054f0a4 19#include "stdio-util.h"
8b43440b 20#include "string-table.h"
07630cea 21#include "string-util.h"
4f5dd394 22#include "strv.h"
288a74cc 23#include "terminal-util.h"
4f5dd394
LP
24#include "unit.h"
25#include "virt.h"
97e6a119 26
39a18c60 27Job* job_new_raw(Unit *unit) {
60918275
LP
28 Job *j;
29
39a18c60
MS
30 /* used for deserialization */
31
87f0e418 32 assert(unit);
60918275 33
39a18c60
MS
34 j = new0(Job, 1);
35 if (!j)
60918275
LP
36 return NULL;
37
668ad332 38 j->manager = unit->manager;
87f0e418 39 j->unit = unit;
e0209d83 40 j->type = _JOB_TYPE_INVALID;
a7a7163d 41 j->reloaded = false;
faf919f1 42
39a18c60
MS
43 return j;
44}
45
46Job* job_new(Unit *unit, JobType type) {
47 Job *j;
48
49 assert(type < _JOB_TYPE_MAX);
50
51 j = job_new_raw(unit);
52 if (!j)
53 return NULL;
54
55 j->id = j->manager->current_job_id++;
56 j->type = type;
57
e5b5ae50 58 /* We don't link it here, that's what job_dependency() is for */
60918275
LP
59
60 return j;
61}
62
a7a7163d 63void job_unlink(Job *j) {
97e7d748
MS
64 assert(j);
65 assert(!j->installed);
02a3bcc6
MS
66 assert(!j->transaction_prev);
67 assert(!j->transaction_next);
68 assert(!j->subject_list);
69 assert(!j->object_list);
60918275 70
a7a7163d 71 if (j->in_run_queue) {
71fda00f 72 LIST_REMOVE(run_queue, j->manager->run_queue, j);
a7a7163d
DT
73 j->in_run_queue = false;
74 }
c1e1601e 75
a7a7163d 76 if (j->in_dbus_queue) {
71fda00f 77 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
a7a7163d
DT
78 j->in_dbus_queue = false;
79 }
c1e1601e 80
a7a7163d 81 if (j->in_gc_queue) {
c5a97ed1 82 LIST_REMOVE(gc_queue, j->manager->gc_job_queue, j);
a7a7163d
DT
83 j->in_gc_queue = false;
84 }
c5a97ed1 85
a7a7163d
DT
86 j->timer_event_source = sd_event_source_unref(j->timer_event_source);
87}
88
89void job_free(Job *j) {
90 assert(j);
91 assert(!j->installed);
92 assert(!j->transaction_prev);
93 assert(!j->transaction_next);
94 assert(!j->subject_list);
95 assert(!j->object_list);
96
97 job_unlink(j);
faf919f1 98
1a465207 99 sd_bus_track_unref(j->bus_track);
b39a2770 100 strv_free(j->deserialized_clients);
faf919f1 101
60918275
LP
102 free(j);
103}
a66d02c3 104
9c3349e2
LP
105static void job_set_state(Job *j, JobState state) {
106 assert(j);
107 assert(state >= 0);
108 assert(state < _JOB_STATE_MAX);
109
110 if (j->state == state)
111 return;
112
113 j->state = state;
114
115 if (!j->installed)
116 return;
117
118 if (j->state == JOB_RUNNING)
119 j->unit->manager->n_running_jobs++;
120 else {
121 assert(j->state == JOB_WAITING);
122 assert(j->unit->manager->n_running_jobs > 0);
123
124 j->unit->manager->n_running_jobs--;
125
126 if (j->unit->manager->n_running_jobs <= 0)
127 j->unit->manager->jobs_in_progress_event_source = sd_event_source_unref(j->unit->manager->jobs_in_progress_event_source);
128 }
129}
130
05d576f1 131void job_uninstall(Job *j) {
e0209d83
MS
132 Job **pj;
133
05d576f1 134 assert(j->installed);
e0209d83 135
9c3349e2
LP
136 job_set_state(j, JOB_WAITING);
137
e0209d83
MS
138 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
139 assert(*pj == j);
140
05d576f1
MS
141 /* Detach from next 'bigger' objects */
142
39a18c60 143 /* daemon-reload should be transparent to job observers */
2c289ea8 144 if (!MANAGER_IS_RELOADING(j->manager))
39a18c60 145 bus_job_send_removed_signal(j);
05d576f1 146
e0209d83
MS
147 *pj = NULL;
148
d6a093d0 149 unit_add_to_gc_queue(j->unit);
05d576f1
MS
150
151 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
152 j->installed = false;
153}
154
656bbffc
MS
155static bool job_type_allows_late_merge(JobType t) {
156 /* Tells whether it is OK to merge a job of type 't' with an already
157 * running job.
158 * Reloads cannot be merged this way. Think of the sequence:
159 * 1. Reload of a daemon is in progress; the daemon has already loaded
160 * its config file, but hasn't completed the reload operation yet.
161 * 2. Edit foo's config file.
162 * 3. Trigger another reload to have the daemon use the new config.
163 * Should the second reload job be merged into the first one, the daemon
164 * would not know about the new config.
165 * JOB_RESTART jobs on the other hand can be merged, because they get
166 * patched into JOB_START after stopping the unit. So if we see a
167 * JOB_RESTART running, it means the unit hasn't stopped yet and at
168 * this time the merge is still allowed. */
e0209d83 169 return t != JOB_RELOAD;
656bbffc
MS
170}
171
172static void job_merge_into_installed(Job *j, Job *other) {
173 assert(j->installed);
174 assert(j->unit == other->unit);
175
e0209d83
MS
176 if (j->type != JOB_NOP)
177 job_type_merge_and_collapse(&j->type, other->type, j->unit);
178 else
179 assert(other->type == JOB_NOP);
656bbffc 180
23ade460 181 j->irreversible = j->irreversible || other->irreversible;
e45460d6 182 j->ignore_order = j->ignore_order || other->ignore_order;
656bbffc
MS
183}
184
185Job* job_install(Job *j) {
e0209d83
MS
186 Job **pj;
187 Job *uj;
05d576f1 188
656bbffc 189 assert(!j->installed);
e0209d83 190 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
9c3349e2 191 assert(j->state == JOB_WAITING);
e0209d83
MS
192
193 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
194 uj = *pj;
656bbffc 195
05d576f1 196 if (uj) {
61da906a 197 if (job_type_is_conflicting(uj->type, j->type))
833f92ad 198 job_finish_and_invalidate(uj, JOB_CANCELED, false, false);
656bbffc
MS
199 else {
200 /* not conflicting, i.e. mergeable */
201
61da906a 202 if (uj->state == JOB_WAITING ||
656bbffc
MS
203 (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
204 job_merge_into_installed(uj, j);
f2341e0a 205 log_unit_debug(uj->unit,
66870f90
ZJS
206 "Merged into installed job %s/%s as %u",
207 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
656bbffc
MS
208 return uj;
209 } else {
210 /* already running and not safe to merge into */
211 /* Patch uj to become a merged job and re-run it. */
212 /* XXX It should be safer to queue j to run after uj finishes, but it is
213 * not currently possible to have more than one installed job per unit. */
214 job_merge_into_installed(uj, j);
f2341e0a 215 log_unit_debug(uj->unit,
66870f90
ZJS
216 "Merged into running job, re-running: %s/%s as %u",
217 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
9c3349e2
LP
218
219 job_set_state(uj, JOB_WAITING);
656bbffc
MS
220 return uj;
221 }
222 }
05d576f1
MS
223 }
224
656bbffc 225 /* Install the job */
e0209d83 226 *pj = j;
05d576f1 227 j->installed = true;
9c3349e2 228
313cefa1 229 j->manager->n_installed_jobs++;
f2341e0a 230 log_unit_debug(j->unit,
66870f90
ZJS
231 "Installed new job %s/%s as %u",
232 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
c5a97ed1
LP
233
234 job_add_to_gc_queue(j);
235
656bbffc 236 return j;
05d576f1
MS
237}
238
e0209d83
MS
239int job_install_deserialized(Job *j) {
240 Job **pj;
241
39a18c60
MS
242 assert(!j->installed);
243
e0209d83
MS
244 if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
245 log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
246 return -EINVAL;
247 }
248
249 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
e0209d83 250 if (*pj) {
f2341e0a 251 log_unit_debug(j->unit, "Unit already has a job installed. Not installing deserialized job.");
e0209d83 252 return -EEXIST;
39a18c60 253 }
9c3349e2 254
e0209d83 255 *pj = j;
39a18c60 256 j->installed = true;
a7a7163d 257 j->reloaded = true;
9c3349e2
LP
258
259 if (j->state == JOB_RUNNING)
260 j->unit->manager->n_running_jobs++;
261
f2341e0a 262 log_unit_debug(j->unit,
66870f90
ZJS
263 "Reinstalled deserialized job %s/%s as %u",
264 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
e0209d83 265 return 0;
39a18c60
MS
266}
267
1da4264f 268JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
e5b5ae50
LP
269 JobDependency *l;
270
271 assert(object);
272
273 /* Adds a new job link, which encodes that the 'subject' job
274 * needs the 'object' job in some way. If 'subject' is NULL
275 * this means the 'anchor' job (i.e. the one the user
35b8ca3a 276 * explicitly asked for) is the requester. */
e5b5ae50 277
0a23a627
LP
278 l = new0(JobDependency, 1);
279 if (!l)
e5b5ae50
LP
280 return NULL;
281
282 l->subject = subject;
283 l->object = object;
284 l->matters = matters;
69dd2852 285 l->conflicts = conflicts;
e5b5ae50 286
44d8db9e 287 if (subject)
71fda00f 288 LIST_PREPEND(subject, subject->subject_list, l);
e5b5ae50 289
71fda00f 290 LIST_PREPEND(object, object->object_list, l);
e5b5ae50
LP
291
292 return l;
293}
294
1da4264f 295void job_dependency_free(JobDependency *l) {
e5b5ae50
LP
296 assert(l);
297
44d8db9e 298 if (l->subject)
71fda00f 299 LIST_REMOVE(subject, l->subject->subject_list, l);
e5b5ae50 300
71fda00f 301 LIST_REMOVE(object, l->object->object_list, l);
e5b5ae50
LP
302
303 free(l);
304}
305
1ffba6fe 306void job_dump(Job *j, FILE*f, const char *prefix) {
a66d02c3
LP
307 assert(j);
308 assert(f);
309
ad5d4b17 310 prefix = strempty(prefix);
9eb63b3c 311
ceed3570 312 fprintf(f,
40d50879
LP
313 "%s-> Job %u:\n"
314 "%s\tAction: %s -> %s\n"
5cb5a6ff 315 "%s\tState: %s\n"
f698d99c
ZJS
316 "%s\tIrreversible: %s\n"
317 "%s\tMay GC: %s\n",
ceed3570 318 prefix, j->id,
ac155bb8 319 prefix, j->unit->id, job_type_to_string(j->type),
94f04347 320 prefix, job_state_to_string(j->state),
f698d99c
ZJS
321 prefix, yes_no(j->irreversible),
322 prefix, yes_no(job_may_gc(j)));
a66d02c3 323}
e5b5ae50 324
348e27fe
MS
325/*
326 * Merging is commutative, so imagine the matrix as symmetric. We store only
327 * its lower triangle to avoid duplication. We don't store the main diagonal,
328 * because A merged with A is simply A.
329 *
e0209d83
MS
330 * If the resulting type is collapsed immediately afterwards (to get rid of
331 * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
332 * the following properties hold:
333 *
48b4eab4 334 * Merging is associative! A merged with B, and then merged with C is the same
103635db 335 * as A merged with the result of B merged with C.
348e27fe
MS
336 *
337 * Mergeability is transitive! If A can be merged with B and B with C then
338 * A also with C.
339 *
340 * Also, if A merged with B cannot be merged with C, then either A or B cannot
341 * be merged with C either.
342 */
343static const JobType job_merging_table[] = {
e0209d83
MS
344/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
345/*********************************************************************************/
348e27fe
MS
346/*JOB_START */
347/*JOB_VERIFY_ACTIVE */ JOB_START,
348/*JOB_STOP */ -1, -1,
349/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
e0209d83 350/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
348e27fe
MS
351};
352
353JobType job_type_lookup_merge(JobType a, JobType b) {
e0209d83
MS
354 assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
355 assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
356 assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
1ffba6fe
LP
357
358 if (a == b)
348e27fe 359 return a;
1ffba6fe 360
348e27fe
MS
361 if (a < b) {
362 JobType tmp = a;
363 a = b;
364 b = tmp;
1ffba6fe 365 }
e094e853 366
348e27fe 367 return job_merging_table[(a - 1) * a / 2 + b];
e094e853 368}
cd2dbd7d 369
593fbdd2
LP
370bool job_type_is_redundant(JobType a, UnitActiveState b) {
371 switch (a) {
372
373 case JOB_START:
3742095b 374 return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
593fbdd2
LP
375
376 case JOB_STOP:
3742095b 377 return IN_SET(b, UNIT_INACTIVE, UNIT_FAILED);
593fbdd2
LP
378
379 case JOB_VERIFY_ACTIVE:
3742095b 380 return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
593fbdd2
LP
381
382 case JOB_RELOAD:
383 return
032ff4af 384 b == UNIT_RELOADING;
593fbdd2 385
593fbdd2
LP
386 case JOB_RESTART:
387 return
388 b == UNIT_ACTIVATING;
389
7e803f5e
MS
390 case JOB_NOP:
391 return true;
392
e0209d83
MS
393 default:
394 assert_not_reached("Invalid job type");
395 }
396}
397
c6497ccb 398JobType job_type_collapse(JobType t, Unit *u) {
e0209d83
MS
399 UnitActiveState s;
400
c6497ccb 401 switch (t) {
e0209d83 402
593fbdd2 403 case JOB_TRY_RESTART:
e0209d83
MS
404 s = unit_active_state(u);
405 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
c6497ccb
LP
406 return JOB_NOP;
407
408 return JOB_RESTART;
e0209d83 409
3282591d
LP
410 case JOB_TRY_RELOAD:
411 s = unit_active_state(u);
412 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
413 return JOB_NOP;
414
415 return JOB_RELOAD;
416
e0209d83
MS
417 case JOB_RELOAD_OR_START:
418 s = unit_active_state(u);
419 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
c6497ccb
LP
420 return JOB_START;
421
422 return JOB_RELOAD;
593fbdd2
LP
423
424 default:
c6497ccb 425 return t;
593fbdd2
LP
426 }
427}
428
e0209d83 429int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
c6497ccb
LP
430 JobType t;
431
432 t = job_type_lookup_merge(*a, b);
e0209d83
MS
433 if (t < 0)
434 return -EEXIST;
c6497ccb
LP
435
436 *a = job_type_collapse(t, u);
e0209d83
MS
437 return 0;
438}
439
9588bc32 440static bool job_is_runnable(Job *j) {
034c6ed7 441 Iterator i;
87f0e418 442 Unit *other;
eef85c4a 443 void *v;
5cb5a6ff
LP
444
445 assert(j);
ac1135be 446 assert(j->installed);
5cb5a6ff 447
87f0e418 448 /* Checks whether there is any job running for the units this
5cb5a6ff 449 * job needs to be running after (in the case of a 'positive'
e67c3609
LP
450 * job type) or before (in the case of a 'negative' job
451 * type. */
452
66ca4ec4
LP
453 /* Note that unit types have a say in what is runnable,
454 * too. For example, if they return -EAGAIN from
455 * unit_start() they can indicate they are not
456 * runnable yet. */
457
e67c3609 458 /* First check if there is an override */
cebe0d41 459 if (j->ignore_order)
e67c3609 460 return true;
5cb5a6ff 461
e0209d83
MS
462 if (j->type == JOB_NOP)
463 return true;
464
0a23a627 465 if (IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD)) {
5cb5a6ff 466 /* Immediate result is that the job is or might be
fc08079e 467 * started. In this case let's wait for the
5cb5a6ff
LP
468 * dependencies, regardless whether they are
469 * starting or stopping something. */
470
eef85c4a 471 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i)
ac155bb8 472 if (other->job)
5cb5a6ff
LP
473 return false;
474 }
475
476 /* Also, if something else is being stopped and we should
fc08079e 477 * change state after it, then let's wait. */
5cb5a6ff 478
eef85c4a 479 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i)
ac155bb8 480 if (other->job &&
0a23a627 481 IN_SET(other->job->type, JOB_STOP, JOB_RESTART))
5cb5a6ff
LP
482 return false;
483
484 /* This means that for a service a and a service b where b
485 * shall be started after a:
486 *
487 * start a + start b → 1st step start a, 2nd step start b
488 * start a + stop b → 1st step stop b, 2nd step start a
489 * stop a + start b → 1st step stop a, 2nd step start b
490 * stop a + stop b → 1st step stop b, 2nd step stop a
491 *
492 * This has the side effect that restarts are properly
493 * synchronized too. */
494
495 return true;
496}
497
bbd1a837 498static void job_change_type(Job *j, JobType newtype) {
f2341e0a
LP
499 assert(j);
500
501 log_unit_debug(j->unit,
66870f90
ZJS
502 "Converting job %s/%s -> %s/%s",
503 j->unit->id, job_type_to_string(j->type),
504 j->unit->id, job_type_to_string(newtype));
bbd1a837
MS
505
506 j->type = newtype;
507}
508
d1a34ae9 509static int job_perform_on_unit(Job **j) {
df446f96
LP
510 uint32_t id;
511 Manager *m;
512 JobType t;
513 Unit *u;
d1a34ae9
MS
514 int r;
515
df446f96
LP
516 /* While we execute this operation the job might go away (for
517 * example: because it finishes immediately or is replaced by
518 * a new, conflicting job.) To make sure we don't access a
519 * freed job later on we store the id here, so that we can
520 * verify the job is still valid. */
521
522 assert(j);
523 assert(*j);
524
525 m = (*j)->manager;
526 u = (*j)->unit;
527 t = (*j)->type;
528 id = (*j)->id;
529
d1a34ae9
MS
530 switch (t) {
531 case JOB_START:
532 r = unit_start(u);
533 break;
534
535 case JOB_RESTART:
536 t = JOB_STOP;
4831981d 537 _fallthrough_;
d1a34ae9
MS
538 case JOB_STOP:
539 r = unit_stop(u);
540 break;
541
542 case JOB_RELOAD:
543 r = unit_reload(u);
544 break;
545
546 default:
547 assert_not_reached("Invalid job type");
548 }
549
550 /* Log if the job still exists and the start/stop/reload function
551 * actually did something. */
552 *j = manager_get_job(m, id);
553 if (*j && r > 0)
554 unit_status_emit_starting_stopping_reloading(u, t);
555
556 return r;
557}
558
5cb5a6ff
LP
559int job_run_and_invalidate(Job *j) {
560 int r;
ac1135be 561
5cb5a6ff 562 assert(j);
ac1135be 563 assert(j->installed);
e0209d83 564 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
66aa6f7f 565 assert(j->in_run_queue);
5cb5a6ff 566
71fda00f 567 LIST_REMOVE(run_queue, j->manager->run_queue, j);
66aa6f7f 568 j->in_run_queue = false;
5cb5a6ff
LP
569
570 if (j->state != JOB_WAITING)
571 return 0;
572
034c6ed7
LP
573 if (!job_is_runnable(j))
574 return -EAGAIN;
575
a2df3ea4 576 job_start_timer(j, true);
9c3349e2 577 job_set_state(j, JOB_RUNNING);
c1e1601e 578 job_add_to_dbus_queue(j);
83c60c9f 579
5cb5a6ff
LP
580 switch (j->type) {
581
5cb5a6ff 582 case JOB_VERIFY_ACTIVE: {
87f0e418
LP
583 UnitActiveState t = unit_active_state(j->unit);
584 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
5cb5a6ff 585 r = -EALREADY;
87f0e418 586 else if (t == UNIT_ACTIVATING)
5cb5a6ff
LP
587 r = -EAGAIN;
588 else
6a371e23 589 r = -EBADR;
5cb5a6ff
LP
590 break;
591 }
592
d1a34ae9 593 case JOB_START:
5cb5a6ff 594 case JOB_STOP:
dd17d388 595 case JOB_RESTART:
d1a34ae9 596 r = job_perform_on_unit(&j);
57339f47 597
d1a34ae9
MS
598 /* If the unit type does not support starting/stopping,
599 * then simply wait. */
57339f47
LP
600 if (r == -EBADR)
601 r = 0;
5cb5a6ff
LP
602 break;
603
604 case JOB_RELOAD:
d1a34ae9 605 r = job_perform_on_unit(&j);
5cb5a6ff
LP
606 break;
607
e0209d83
MS
608 case JOB_NOP:
609 r = -EALREADY;
610 break;
611
5cb5a6ff 612 default:
44d8db9e 613 assert_not_reached("Unknown job type");
5cb5a6ff
LP
614 }
615
e0209d83 616 if (j) {
2cf19a7a 617 if (r == -EALREADY)
833f92ad 618 r = job_finish_and_invalidate(j, JOB_DONE, true, true);
6a371e23 619 else if (r == -EBADR)
833f92ad 620 r = job_finish_and_invalidate(j, JOB_SKIPPED, true, false);
6a371e23 621 else if (r == -ENOEXEC)
833f92ad 622 r = job_finish_and_invalidate(j, JOB_INVALID, true, false);
59fccdc5 623 else if (r == -EPROTO)
833f92ad 624 r = job_finish_and_invalidate(j, JOB_ASSERT, true, false);
15411c0c 625 else if (r == -EOPNOTSUPP)
833f92ad 626 r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true, false);
631b676b
LP
627 else if (r == -ENOLINK)
628 r = job_finish_and_invalidate(j, JOB_DEPENDENCY, true, false);
d4fd1cf2
LP
629 else if (r == -ESTALE)
630 r = job_finish_and_invalidate(j, JOB_ONCE, true, false);
9c3349e2
LP
631 else if (r == -EAGAIN)
632 job_set_state(j, JOB_WAITING);
633 else if (r < 0)
833f92ad 634 r = job_finish_and_invalidate(j, JOB_FAILED, true, false);
2cf19a7a 635 }
5cb5a6ff
LP
636
637 return r;
638}
639
44a6b1b6 640_pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
df446f96 641
aa49ab5f
MS
642 static const char *const generic_finished_start_job[_JOB_RESULT_MAX] = {
643 [JOB_DONE] = "Started %s.",
644 [JOB_TIMEOUT] = "Timed out starting %s.",
645 [JOB_FAILED] = "Failed to start %s.",
646 [JOB_DEPENDENCY] = "Dependency failed for %s.",
647 [JOB_ASSERT] = "Assertion failed for %s.",
648 [JOB_UNSUPPORTED] = "Starting of %s not supported.",
4332edf6 649 [JOB_COLLECTED] = "Unnecessary job for %s was removed.",
d4fd1cf2 650 [JOB_ONCE] = "Unit %s has been started before and cannot be started again."
aa49ab5f
MS
651 };
652 static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = {
653 [JOB_DONE] = "Stopped %s.",
654 [JOB_FAILED] = "Stopped (with error) %s.",
b59f0ecd 655 [JOB_TIMEOUT] = "Timed out stopping %s.",
aa49ab5f
MS
656 };
657 static const char *const generic_finished_reload_job[_JOB_RESULT_MAX] = {
658 [JOB_DONE] = "Reloaded %s.",
659 [JOB_FAILED] = "Reload failed for %s.",
660 [JOB_TIMEOUT] = "Timed out reloading %s.",
661 };
662 /* When verify-active detects the unit is inactive, report it.
663 * Most likely a DEPEND warning from a requisiting unit will
664 * occur next and it's nice to see what was requisited. */
665 static const char *const generic_finished_verify_active_job[_JOB_RESULT_MAX] = {
666 [JOB_SKIPPED] = "%s is not active.",
667 };
877d54e9 668
df446f96
LP
669 const UnitStatusMessageFormats *format_table;
670 const char *format;
671
877d54e9
LP
672 assert(u);
673 assert(t >= 0);
674 assert(t < _JOB_TYPE_MAX);
c6918296 675
df446f96 676 if (IN_SET(t, JOB_START, JOB_STOP, JOB_RESTART)) {
aa49ab5f
MS
677 format_table = &UNIT_VTABLE(u)->status_message_formats;
678 if (format_table) {
679 format = t == JOB_START ? format_table->finished_start_job[result] :
680 format_table->finished_stop_job[result];
681 if (format)
682 return format;
683 }
684 }
877d54e9 685
aa49ab5f 686 /* Return generic strings */
877d54e9 687 if (t == JOB_START)
aa49ab5f 688 return generic_finished_start_job[result];
4c701096 689 else if (IN_SET(t, JOB_STOP, JOB_RESTART))
aa49ab5f
MS
690 return generic_finished_stop_job[result];
691 else if (t == JOB_RELOAD)
692 return generic_finished_reload_job[result];
693 else if (t == JOB_VERIFY_ACTIVE)
694 return generic_finished_verify_active_job[result];
877d54e9
LP
695
696 return NULL;
697}
698
047d7219
ZJS
699static const struct {
700 const char *color, *word;
701} job_print_status_messages [_JOB_RESULT_MAX] = {
96164a39 702 [JOB_DONE] = { ANSI_OK_COLOR, " OK " },
047d7219
ZJS
703 [JOB_TIMEOUT] = { ANSI_HIGHLIGHT_RED, " TIME " },
704 [JOB_FAILED] = { ANSI_HIGHLIGHT_RED, "FAILED" },
705 [JOB_DEPENDENCY] = { ANSI_HIGHLIGHT_YELLOW, "DEPEND" },
706 [JOB_SKIPPED] = { ANSI_HIGHLIGHT, " INFO " },
707 [JOB_ASSERT] = { ANSI_HIGHLIGHT_YELLOW, "ASSERT" },
708 [JOB_UNSUPPORTED] = { ANSI_HIGHLIGHT_YELLOW, "UNSUPP" },
709 /* JOB_COLLECTED */
d4fd1cf2 710 [JOB_ONCE] = { ANSI_HIGHLIGHT_RED, " ONCE " },
047d7219 711};
e02cd6f7 712
047d7219 713static void job_print_status_message(Unit *u, JobType t, JobResult result) {
df446f96 714 const char *format;
dc9b5816 715 const char *status;
df446f96 716
877d54e9
LP
717 assert(u);
718 assert(t >= 0);
719 assert(t < _JOB_TYPE_MAX);
720
df446f96
LP
721 /* Reload status messages have traditionally not been printed to console. */
722 if (t == JOB_RELOAD)
723 return;
724
047d7219
ZJS
725 if (!job_print_status_messages[result].word)
726 return;
727
aa49ab5f
MS
728 format = job_get_status_message_format(u, t, result);
729 if (!format)
730 return;
e02cd6f7 731
dc9b5816 732 if (log_get_show_color())
047d7219
ZJS
733 status = strjoina(job_print_status_messages[result].color,
734 job_print_status_messages[result].word,
735 ANSI_NORMAL);
dc9b5816 736 else
047d7219 737 status = job_print_status_messages[result].word;
dc9b5816 738
aa49ab5f
MS
739 if (result != JOB_DONE)
740 manager_flip_auto_status(u->manager, true);
e02cd6f7 741
aa49ab5f 742 DISABLE_WARNING_FORMAT_NONLITERAL;
dc9b5816 743 unit_status_printf(u, status, format);
aa49ab5f 744 REENABLE_WARNING;
7cf82e0b 745
aa49ab5f 746 if (t == JOB_START && result == JOB_FAILED) {
df446f96 747 _cleanup_free_ char *quoted;
7cf82e0b 748
804ee07c 749 quoted = shell_maybe_quote(u->id, ESCAPE_BACKSLASH);
df446f96 750 manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted));
e02cd6f7
LP
751 }
752}
753
877d54e9 754static void job_log_status_message(Unit *u, JobType t, JobResult result) {
2b044526 755 const char *format, *mid;
877d54e9 756 char buf[LINE_MAX];
64f575d2
MS
757 static const int job_result_log_level[_JOB_RESULT_MAX] = {
758 [JOB_DONE] = LOG_INFO,
759 [JOB_CANCELED] = LOG_INFO,
760 [JOB_TIMEOUT] = LOG_ERR,
761 [JOB_FAILED] = LOG_ERR,
762 [JOB_DEPENDENCY] = LOG_WARNING,
763 [JOB_SKIPPED] = LOG_NOTICE,
764 [JOB_INVALID] = LOG_INFO,
765 [JOB_ASSERT] = LOG_WARNING,
766 [JOB_UNSUPPORTED] = LOG_WARNING,
c5a97ed1 767 [JOB_COLLECTED] = LOG_INFO,
d4fd1cf2 768 [JOB_ONCE] = LOG_ERR,
64f575d2 769 };
877d54e9
LP
770
771 assert(u);
772 assert(t >= 0);
773 assert(t < _JOB_TYPE_MAX);
774
047d7219
ZJS
775 /* Skip printing if output goes to the console, and job_print_status_message()
776 will actually print something to the console. */
777 if (log_on_console() && job_print_status_messages[result].word)
81270860
LP
778 return;
779
aa49ab5f 780 format = job_get_status_message_format(u, t, result);
877d54e9
LP
781 if (!format)
782 return;
783
574432f8
ILG
784 /* The description might be longer than the buffer, but that's OK,
785 * we'll just truncate it here. Note that we use snprintf() rather than
786 * xsprintf() on purpose here: we are fine with truncation and don't
787 * consider that an error. */
bcfce235 788 DISABLE_WARNING_FORMAT_NONLITERAL;
574432f8 789 (void) snprintf(buf, sizeof(buf), format, unit_description(u));
bcfce235 790 REENABLE_WARNING;
877d54e9 791
df446f96
LP
792 switch (t) {
793
794 case JOB_START:
2b044526
ZJS
795 if (result == JOB_DONE)
796 mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTED_STR;
797 else
798 mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILED_STR;
df446f96
LP
799 break;
800
801 case JOB_RELOAD:
2b044526 802 mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADED_STR;
df446f96
LP
803 break;
804
805 case JOB_STOP:
806 case JOB_RESTART:
2b044526 807 mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPED_STR;
df446f96
LP
808 break;
809
810 default:
64f575d2 811 log_struct(job_result_log_level[result],
4f29c6fe 812 LOG_MESSAGE("%s", buf),
646cc98d
LP
813 "JOB_TYPE=%s", job_type_to_string(t),
814 "JOB_RESULT=%s", job_result_to_string(result),
ba360bb0 815 LOG_UNIT_ID(u),
a1230ff9 816 LOG_UNIT_INVOCATION_ID(u));
b81bbe53
MS
817 return;
818 }
819
64f575d2 820 log_struct(job_result_log_level[result],
b81bbe53 821 LOG_MESSAGE("%s", buf),
646cc98d
LP
822 "JOB_TYPE=%s", job_type_to_string(t),
823 "JOB_RESULT=%s", job_result_to_string(result),
ba360bb0 824 LOG_UNIT_ID(u),
f1c50bec 825 LOG_UNIT_INVOCATION_ID(u),
a1230ff9 826 mid);
877d54e9 827}
877d54e9 828
30961fa3 829static void job_emit_status_message(Unit *u, JobType t, JobResult result) {
646cc98d 830 assert(u);
30961fa3
MS
831
832 /* No message if the job did not actually do anything due to failed condition. */
833 if (t == JOB_START && result == JOB_DONE && !u->condition_result)
834 return;
835
836 job_log_status_message(u, t, result);
df446f96 837 job_print_status_message(u, t, result);
30961fa3
MS
838}
839
be7d9ff7
LP
840static void job_fail_dependencies(Unit *u, UnitDependency d) {
841 Unit *other;
842 Iterator i;
eef85c4a 843 void *v;
be7d9ff7
LP
844
845 assert(u);
846
eef85c4a 847 HASHMAP_FOREACH_KEY(v, other, u->dependencies[d], i) {
be7d9ff7
LP
848 Job *j = other->job;
849
850 if (!j)
851 continue;
852 if (!IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE))
853 continue;
854
833f92ad 855 job_finish_and_invalidate(j, JOB_DEPENDENCY, true, false);
be7d9ff7
LP
856 }
857}
858
a7a7163d
DT
859static int job_save_pending_finished_job(Job *j) {
860 int r;
861
862 assert(j);
863
864 r = set_ensure_allocated(&j->manager->pending_finished_jobs, NULL);
865 if (r < 0)
866 return r;
867
868 job_unlink(j);
869 return set_put(j->manager->pending_finished_jobs, j);
870}
871
833f92ad 872int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already) {
87f0e418
LP
873 Unit *u;
874 Unit *other;
b866264a 875 JobType t;
034c6ed7 876 Iterator i;
eef85c4a 877 void *v;
5cb5a6ff
LP
878
879 assert(j);
ac1135be 880 assert(j->installed);
e0209d83 881 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
5cb5a6ff 882
c6918296
MS
883 u = j->unit;
884 t = j->type;
885
886 j->result = result;
887
f2341e0a 888 log_unit_debug(u, "Job %s/%s finished, result=%s", u->id, job_type_to_string(t), job_result_to_string(result));
c6918296 889
833f92ad
MS
890 /* If this job did nothing to respective unit we don't log the status message */
891 if (!already)
892 job_emit_status_message(u, t, result);
c6918296 893
034c6ed7 894 /* Patch restart jobs so that they become normal start jobs */
c6918296 895 if (result == JOB_DONE && t == JOB_RESTART) {
f50e0a01 896
bbd1a837 897 job_change_type(j, JOB_START);
9c3349e2 898 job_set_state(j, JOB_WAITING);
cc42e081 899
fec7615c 900 job_add_to_dbus_queue(j);
cc42e081 901 job_add_to_run_queue(j);
c5a97ed1 902 job_add_to_gc_queue(j);
57981b98 903
57981b98 904 goto finish;
5cb5a6ff
LP
905 }
906
3742095b 907 if (IN_SET(result, JOB_FAILED, JOB_INVALID))
313cefa1 908 j->manager->n_failed_jobs++;
76bf48b7 909
97e7d748 910 job_uninstall(j);
509ad789
ZJS
911 /* Keep jobs started before the reload to send singal later, free all others */
912 if (!MANAGER_IS_RELOADING(j->manager) ||
913 !j->reloaded ||
914 job_save_pending_finished_job(j) < 0)
a7a7163d 915 job_free(j);
5cb5a6ff
LP
916
917 /* Fail depending jobs on failure */
5273510e 918 if (result != JOB_DONE && recursive) {
be7d9ff7
LP
919 if (IN_SET(t, JOB_START, JOB_VERIFY_ACTIVE)) {
920 job_fail_dependencies(u, UNIT_REQUIRED_BY);
921 job_fail_dependencies(u, UNIT_REQUISITE_OF);
922 job_fail_dependencies(u, UNIT_BOUND_BY);
be7d9ff7
LP
923 } else if (t == JOB_STOP)
924 job_fail_dependencies(u, UNIT_CONFLICTED_BY);
5cb5a6ff
LP
925 }
926
c0daa706 927 /* Trigger OnFailure dependencies that are not generated by
66870f90 928 * the unit itself. We don't treat JOB_CANCELED as failure in
c0daa706
LP
929 * this context. And JOB_FAILURE is already handled by the
930 * unit itself. */
646cc98d 931 if (IN_SET(result, JOB_TIMEOUT, JOB_DEPENDENCY)) {
f2341e0a
LP
932 log_struct(LOG_NOTICE,
933 "JOB_TYPE=%s", job_type_to_string(t),
934 "JOB_RESULT=%s", job_result_to_string(result),
935 LOG_UNIT_ID(u),
936 LOG_UNIT_MESSAGE(u, "Job %s/%s failed with result '%s'.",
e2cc6eca
LP
937 u->id,
938 job_type_to_string(t),
a1230ff9 939 job_result_to_string(result)));
222ae6a8 940
3ecaa09b 941 unit_start_on_failure(u);
222ae6a8 942 }
c0daa706 943
3ecaa09b
LP
944 unit_trigger_notify(u);
945
57981b98 946finish:
5cb5a6ff 947 /* Try to start the next jobs that can be started */
eef85c4a 948 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_AFTER], i)
c5a97ed1 949 if (other->job) {
ac155bb8 950 job_add_to_run_queue(other->job);
c5a97ed1
LP
951 job_add_to_gc_queue(other->job);
952 }
eef85c4a 953 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BEFORE], i)
c5a97ed1 954 if (other->job) {
ac155bb8 955 job_add_to_run_queue(other->job);
c5a97ed1
LP
956 job_add_to_gc_queue(other->job);
957 }
5cb5a6ff 958
ac155bb8 959 manager_check_finished(u->manager);
b0c918b9 960
5273510e 961 return 0;
5cb5a6ff 962}
034c6ed7 963
718db961
LP
964static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) {
965 Job *j = userdata;
f189ab18 966 Unit *u;
faf919f1 967
718db961
LP
968 assert(j);
969 assert(s == j->timer_event_source);
faf919f1 970
f2341e0a 971 log_unit_warning(j->unit, "Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
faf919f1 972
f189ab18 973 u = j->unit;
833f92ad 974 job_finish_and_invalidate(j, JOB_TIMEOUT, true, false);
f189ab18 975
87a47f99 976 emergency_action(u->manager, u->job_timeout_action, u->job_timeout_reboot_arg, "job timed out");
f189ab18 977
718db961
LP
978 return 0;
979}
faf919f1 980
a2df3ea4 981int job_start_timer(Job *j, bool job_running) {
718db961 982 int r;
171f12ce 983 usec_t timeout_time, old_timeout_time;
faf919f1 984
a2df3ea4 985 if (job_running) {
171f12ce
MK
986 j->begin_running_usec = now(CLOCK_MONOTONIC);
987
a2df3ea4
MK
988 if (j->unit->job_running_timeout == USEC_INFINITY)
989 return 0;
faf919f1 990
171f12ce 991 timeout_time = usec_add(j->begin_running_usec, j->unit->job_running_timeout);
faf919f1 992
a2df3ea4
MK
993 if (j->timer_event_source) {
994 /* Update only if JobRunningTimeoutSec= results in earlier timeout */
995 r = sd_event_source_get_time(j->timer_event_source, &old_timeout_time);
996 if (r < 0)
997 return r;
998
999 if (old_timeout_time <= timeout_time)
1000 return 0;
1001
1002 return sd_event_source_set_time(j->timer_event_source, timeout_time);
1003 }
1004 } else {
1005 if (j->timer_event_source)
1006 return 0;
1007
1008 j->begin_usec = now(CLOCK_MONOTONIC);
1009
1010 if (j->unit->job_timeout == USEC_INFINITY)
1011 return 0;
1012
1013 timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
1014 }
8bb310c3 1015
6a0f1f6d
LP
1016 r = sd_event_add_time(
1017 j->manager->event,
1018 &j->timer_event_source,
1019 CLOCK_MONOTONIC,
a2df3ea4 1020 timeout_time, 0,
6a0f1f6d 1021 job_dispatch_timer, j);
718db961
LP
1022 if (r < 0)
1023 return r;
faf919f1 1024
7dfbe2e3
TG
1025 (void) sd_event_source_set_description(j->timer_event_source, "job-start");
1026
718db961 1027 return 0;
faf919f1
LP
1028}
1029
c1e1601e 1030void job_add_to_run_queue(Job *j) {
034c6ed7 1031 assert(j);
ac1135be 1032 assert(j->installed);
034c6ed7
LP
1033
1034 if (j->in_run_queue)
1035 return;
1036
752b5905
LP
1037 if (!j->manager->run_queue)
1038 sd_event_source_set_enabled(j->manager->run_queue_event_source, SD_EVENT_ONESHOT);
1039
71fda00f 1040 LIST_PREPEND(run_queue, j->manager->run_queue, j);
034c6ed7
LP
1041 j->in_run_queue = true;
1042}
94f04347 1043
c1e1601e
LP
1044void job_add_to_dbus_queue(Job *j) {
1045 assert(j);
1046 assert(j->installed);
1047
1048 if (j->in_dbus_queue)
1049 return;
1050
a567261a
LP
1051 /* We don't check if anybody is subscribed here, since this
1052 * job might just have been created and not yet assigned to a
1053 * connection/client. */
94b6dfa2 1054
71fda00f 1055 LIST_PREPEND(dbus_queue, j->manager->dbus_job_queue, j);
c1e1601e
LP
1056 j->in_dbus_queue = true;
1057}
1058
ea430986
LP
1059char *job_dbus_path(Job *j) {
1060 char *p;
1061
1062 assert(j);
1063
ccd06097 1064 if (asprintf(&p, "/org/freedesktop/systemd1/job/%"PRIu32, j->id) < 0)
ea430986
LP
1065 return NULL;
1066
1067 return p;
1068}
1069
05a98afd
LP
1070int job_serialize(Job *j, FILE *f) {
1071 assert(j);
1072 assert(f);
1073
39a18c60
MS
1074 fprintf(f, "job-id=%u\n", j->id);
1075 fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
1076 fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
23ade460 1077 fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
39a18c60
MS
1078 fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
1079 fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
718db961
LP
1080
1081 if (j->begin_usec > 0)
ccd06097 1082 fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec);
171f12ce
MK
1083 if (j->begin_running_usec > 0)
1084 fprintf(f, "job-begin-running="USEC_FMT"\n", j->begin_running_usec);
718db961 1085
1a465207 1086 bus_track_serialize(j->bus_track, f, "subscribed");
39a18c60
MS
1087
1088 /* End marker */
1089 fputc('\n', f);
1090 return 0;
1091}
1092
05a98afd 1093int job_deserialize(Job *j, FILE *f) {
718db961 1094 assert(j);
05a98afd 1095 assert(f);
718db961 1096
39a18c60
MS
1097 for (;;) {
1098 char line[LINE_MAX], *l, *v;
1099 size_t k;
1100
1101 if (!fgets(line, sizeof(line), f)) {
1102 if (feof(f))
1103 return 0;
1104 return -errno;
1105 }
1106
1107 char_array_0(line);
1108 l = strstrip(line);
1109
1110 /* End marker */
1111 if (l[0] == 0)
1112 return 0;
1113
1114 k = strcspn(l, "=");
1115
1116 if (l[k] == '=') {
1117 l[k] = 0;
1118 v = l+k+1;
1119 } else
1120 v = l+k;
1121
1122 if (streq(l, "job-id")) {
718db961 1123
39a18c60
MS
1124 if (safe_atou32(v, &j->id) < 0)
1125 log_debug("Failed to parse job id value %s", v);
718db961 1126
39a18c60 1127 } else if (streq(l, "job-type")) {
718db961
LP
1128 JobType t;
1129
1130 t = job_type_from_string(v);
39a18c60
MS
1131 if (t < 0)
1132 log_debug("Failed to parse job type %s", v);
e0209d83
MS
1133 else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
1134 log_debug("Cannot deserialize job of type %s", v);
39a18c60
MS
1135 else
1136 j->type = t;
718db961 1137
39a18c60 1138 } else if (streq(l, "job-state")) {
718db961
LP
1139 JobState s;
1140
1141 s = job_state_from_string(v);
39a18c60
MS
1142 if (s < 0)
1143 log_debug("Failed to parse job state %s", v);
1144 else
9c3349e2 1145 job_set_state(j, s);
718db961 1146
23ade460 1147 } else if (streq(l, "job-irreversible")) {
718db961
LP
1148 int b;
1149
1150 b = parse_boolean(v);
23ade460
MS
1151 if (b < 0)
1152 log_debug("Failed to parse job irreversible flag %s", v);
1153 else
1154 j->irreversible = j->irreversible || b;
718db961 1155
39a18c60 1156 } else if (streq(l, "job-sent-dbus-new-signal")) {
718db961
LP
1157 int b;
1158
1159 b = parse_boolean(v);
39a18c60
MS
1160 if (b < 0)
1161 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
1162 else
1163 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
718db961 1164
39a18c60 1165 } else if (streq(l, "job-ignore-order")) {
718db961
LP
1166 int b;
1167
1168 b = parse_boolean(v);
39a18c60
MS
1169 if (b < 0)
1170 log_debug("Failed to parse job ignore_order flag %s", v);
1171 else
1172 j->ignore_order = j->ignore_order || b;
718db961
LP
1173
1174 } else if (streq(l, "job-begin")) {
1175 unsigned long long ull;
1176
1177 if (sscanf(v, "%llu", &ull) != 1)
1178 log_debug("Failed to parse job-begin value %s", v);
39a18c60 1179 else
718db961
LP
1180 j->begin_usec = ull;
1181
171f12ce
MK
1182 } else if (streq(l, "job-begin-running")) {
1183 unsigned long long ull;
1184
1185 if (sscanf(v, "%llu", &ull) != 1)
1186 log_debug("Failed to parse job-begin-running value %s", v);
1187 else
1188 j->begin_running_usec = ull;
1189
8f8f05a9 1190 } else if (streq(l, "subscribed")) {
718db961 1191
b39a2770 1192 if (strv_extend(&j->deserialized_clients, v) < 0)
05a98afd 1193 log_oom();
39a18c60
MS
1194 }
1195 }
1196}
1197
1198int job_coldplug(Job *j) {
718db961 1199 int r;
171f12ce 1200 usec_t timeout_time = USEC_INFINITY;
718db961
LP
1201
1202 assert(j);
39a18c60 1203
8f8f05a9
LP
1204 /* After deserialization is complete and the bus connection
1205 * set up again, let's start watching our subscribers again */
c5a97ed1 1206 (void) bus_job_coldplug_bus_track(j);
8f8f05a9 1207
1727a595
MM
1208 if (j->state == JOB_WAITING)
1209 job_add_to_run_queue(j);
1210
c5a97ed1
LP
1211 /* Maybe due to new dependencies we don't actually need this job anymore? */
1212 job_add_to_gc_queue(j);
1213
171f12ce
MK
1214 /* Create timer only when job began or began running and the respective timeout is finite.
1215 * Follow logic of job_start_timer() if both timeouts are finite */
1216 if (j->begin_usec == 0)
1217 return 0;
1218
1219 if (j->unit->job_timeout != USEC_INFINITY)
1220 timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
1221
1222 if (j->begin_running_usec > 0 && j->unit->job_running_timeout != USEC_INFINITY)
1223 timeout_time = MIN(timeout_time, usec_add(j->begin_running_usec, j->unit->job_running_timeout));
1224
1225 if (timeout_time == USEC_INFINITY)
39a18c60
MS
1226 return 0;
1227
36c16a7c 1228 j->timer_event_source = sd_event_source_unref(j->timer_event_source);
39a18c60 1229
6a0f1f6d
LP
1230 r = sd_event_add_time(
1231 j->manager->event,
1232 &j->timer_event_source,
1233 CLOCK_MONOTONIC,
171f12ce 1234 timeout_time, 0,
6a0f1f6d 1235 job_dispatch_timer, j);
718db961 1236 if (r < 0)
da927ba9 1237 log_debug_errno(r, "Failed to restart timeout for job: %m");
718db961 1238
7dfbe2e3
TG
1239 (void) sd_event_source_set_description(j->timer_event_source, "job-timeout");
1240
718db961 1241 return r;
39a18c60
MS
1242}
1243
c65eb836
LP
1244void job_shutdown_magic(Job *j) {
1245 assert(j);
1246
1247 /* The shutdown target gets some special treatment here: we
1248 * tell the kernel to begin with flushing its disk caches, to
1249 * optimize shutdown time a bit. Ideally we wouldn't hardcode
1250 * this magic into PID 1. However all other processes aren't
1251 * options either since they'd exit much sooner than PID 1 and
1252 * asynchronous sync() would cause their exit to be
1253 * delayed. */
1254
c2756a68 1255 if (j->type != JOB_START)
c65eb836
LP
1256 return;
1257
463d0d15 1258 if (!MANAGER_IS_SYSTEM(j->unit->manager))
c2756a68
LP
1259 return;
1260
1261 if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
c65eb836
LP
1262 return;
1263
5b1869ea
OB
1264 /* In case messages on console has been disabled on boot */
1265 j->unit->manager->no_console_output = false;
1266
75f86906 1267 if (detect_container() > 0)
c65eb836
LP
1268 return;
1269
d00c2631 1270 (void) asynchronous_sync(NULL);
c65eb836
LP
1271}
1272
7a7821c8
LP
1273int job_get_timeout(Job *j, usec_t *timeout) {
1274 usec_t x = USEC_INFINITY, y = USEC_INFINITY;
68db7a3b 1275 Unit *u = j->unit;
7a7821c8 1276 int r;
68db7a3b
ZJS
1277
1278 assert(u);
1279
1280 if (j->timer_event_source) {
1281 r = sd_event_source_get_time(j->timer_event_source, &x);
1282 if (r < 0)
1283 return r;
68db7a3b
ZJS
1284 }
1285
1286 if (UNIT_VTABLE(u)->get_timeout) {
7a7821c8
LP
1287 r = UNIT_VTABLE(u)->get_timeout(u, &y);
1288 if (r < 0)
1289 return r;
68db7a3b
ZJS
1290 }
1291
7a7821c8 1292 if (x == USEC_INFINITY && y == USEC_INFINITY)
68db7a3b
ZJS
1293 return 0;
1294
1295 *timeout = MIN(x, y);
68db7a3b
ZJS
1296 return 1;
1297}
1298
2ab3050f 1299bool job_may_gc(Job *j) {
c5a97ed1
LP
1300 Unit *other;
1301 Iterator i;
eef85c4a 1302 void *v;
c5a97ed1
LP
1303
1304 assert(j);
1305
1306 /* Checks whether this job should be GC'ed away. We only do this for jobs of units that have no effect on their
2ab3050f
ZJS
1307 * own and just track external state. For now the only unit type that qualifies for this are .device units.
1308 * Returns true if the job can be collected. */
c5a97ed1
LP
1309
1310 if (!UNIT_VTABLE(j->unit)->gc_jobs)
2ab3050f 1311 return false;
c5a97ed1
LP
1312
1313 if (sd_bus_track_count(j->bus_track) > 0)
2ab3050f 1314 return false;
c5a97ed1
LP
1315
1316 /* FIXME: So this is a bit ugly: for now we don't properly track references made via private bus connections
1317 * (because it's nasty, as sd_bus_track doesn't apply to it). We simply remember that the job was once
1318 * referenced by one, and reset this whenever we notice that no private bus connections are around. This means
1319 * the GC is a bit too conservative when it comes to jobs created by private bus connections. */
1320 if (j->ref_by_private_bus) {
1321 if (set_isempty(j->unit->manager->private_buses))
1322 j->ref_by_private_bus = false;
1323 else
2ab3050f 1324 return false;
c5a97ed1
LP
1325 }
1326
1327 if (j->type == JOB_NOP)
2ab3050f 1328 return false;
c5a97ed1
LP
1329
1330 /* If a job is ordered after ours, and is to be started, then it needs to wait for us, regardless if we stop or
1331 * start, hence let's not GC in that case. */
eef85c4a 1332 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
c5a97ed1
LP
1333 if (!other->job)
1334 continue;
1335
1336 if (other->job->ignore_order)
1337 continue;
1338
1339 if (IN_SET(other->job->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD))
2ab3050f 1340 return false;
c5a97ed1
LP
1341 }
1342
047d7219
ZJS
1343 /* If we are going down, but something else is ordered After= us, then it needs to wait for us */
1344 if (IN_SET(j->type, JOB_STOP, JOB_RESTART))
eef85c4a 1345 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
c5a97ed1
LP
1346 if (!other->job)
1347 continue;
1348
1349 if (other->job->ignore_order)
1350 continue;
1351
2ab3050f 1352 return false;
c5a97ed1 1353 }
c5a97ed1
LP
1354
1355 /* The logic above is kinda the inverse of the job_is_runnable() logic. Specifically, if the job "we" is
1356 * ordered before the job "other":
1357 *
1358 * we start + other start → stay
1359 * we start + other stop → gc
1360 * we stop + other start → stay
1361 * we stop + other stop → gc
1362 *
1363 * "we" are ordered after "other":
1364 *
1365 * we start + other start → gc
1366 * we start + other stop → gc
1367 * we stop + other start → stay
1368 * we stop + other stop → stay
1369 *
1370 */
1371
2ab3050f 1372 return true;
c5a97ed1
LP
1373}
1374
1375void job_add_to_gc_queue(Job *j) {
1376 assert(j);
1377
1378 if (j->in_gc_queue)
1379 return;
1380
2ab3050f 1381 if (!job_may_gc(j))
c5a97ed1
LP
1382 return;
1383
1384 LIST_PREPEND(gc_queue, j->unit->manager->gc_job_queue, j);
1385 j->in_gc_queue = true;
1386}
1387
15ea79f8
LP
1388static int job_compare(const void *a, const void *b) {
1389 Job *x = *(Job**) a, *y = *(Job**) b;
1390
1391 if (x->id < y->id)
1392 return -1;
1393 if (x->id > y->id)
1394 return 1;
1395
1396 return 0;
1397}
1398
1399static size_t sort_job_list(Job **list, size_t n) {
1400 Job *previous = NULL;
1401 size_t a, b;
1402
1403 /* Order by numeric IDs */
1404 qsort_safe(list, n, sizeof(Job*), job_compare);
1405
1406 /* Filter out duplicates */
1407 for (a = 0, b = 0; a < n; a++) {
1408
1409 if (previous == list[a])
1410 continue;
1411
1412 previous = list[b++] = list[a];
1413 }
1414
1415 return b;
1416}
1417
1418int job_get_before(Job *j, Job*** ret) {
1419 _cleanup_free_ Job** list = NULL;
1420 size_t n = 0, n_allocated = 0;
1421 Unit *other = NULL;
1422 Iterator i;
eef85c4a 1423 void *v;
15ea79f8
LP
1424
1425 /* Returns a list of all pending jobs that need to finish before this job may be started. */
1426
1427 assert(j);
1428 assert(ret);
1429
1430 if (j->ignore_order) {
1431 *ret = NULL;
1432 return 0;
1433 }
1434
1435 if (IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD)) {
1436
eef85c4a 1437 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
15ea79f8
LP
1438 if (!other->job)
1439 continue;
1440
1441 if (!GREEDY_REALLOC(list, n_allocated, n+1))
1442 return -ENOMEM;
1443 list[n++] = other->job;
1444 }
1445 }
1446
eef85c4a 1447 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
15ea79f8
LP
1448 if (!other->job)
1449 continue;
1450
1451 if (!IN_SET(other->job->type, JOB_STOP, JOB_RESTART))
1452 continue;
1453
1454 if (!GREEDY_REALLOC(list, n_allocated, n+1))
1455 return -ENOMEM;
1456 list[n++] = other->job;
1457 }
1458
1459 n = sort_job_list(list, n);
1460
1cc6c93a 1461 *ret = TAKE_PTR(list);
15ea79f8
LP
1462
1463 return (int) n;
1464}
1465
1466int job_get_after(Job *j, Job*** ret) {
1467 _cleanup_free_ Job** list = NULL;
1468 size_t n = 0, n_allocated = 0;
1469 Unit *other = NULL;
eef85c4a 1470 void *v;
15ea79f8
LP
1471 Iterator i;
1472
1473 assert(j);
1474 assert(ret);
1475
1476 /* Returns a list of all pending jobs that are waiting for this job to finish. */
1477
eef85c4a 1478 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
15ea79f8
LP
1479 if (!other->job)
1480 continue;
1481
1482 if (other->job->ignore_order)
1483 continue;
1484
1485 if (!IN_SET(other->job->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD))
1486 continue;
1487
1488 if (!GREEDY_REALLOC(list, n_allocated, n+1))
1489 return -ENOMEM;
1490 list[n++] = other->job;
1491 }
1492
1493 if (IN_SET(j->type, JOB_STOP, JOB_RESTART)) {
1494
eef85c4a 1495 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
15ea79f8
LP
1496 if (!other->job)
1497 continue;
1498
1499 if (other->job->ignore_order)
1500 continue;
1501
1502 if (!GREEDY_REALLOC(list, n_allocated, n+1))
1503 return -ENOMEM;
1504 list[n++] = other->job;
1505 }
1506 }
1507
1508 n = sort_job_list(list, n);
1509
1cc6c93a 1510 *ret = TAKE_PTR(list);
15ea79f8
LP
1511
1512 return (int) n;
1513}
1514
94f04347
LP
1515static const char* const job_state_table[_JOB_STATE_MAX] = {
1516 [JOB_WAITING] = "waiting",
0a23a627 1517 [JOB_RUNNING] = "running",
94f04347
LP
1518};
1519
1520DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
1521
1522static const char* const job_type_table[_JOB_TYPE_MAX] = {
1523 [JOB_START] = "start",
1524 [JOB_VERIFY_ACTIVE] = "verify-active",
1525 [JOB_STOP] = "stop",
1526 [JOB_RELOAD] = "reload",
1527 [JOB_RELOAD_OR_START] = "reload-or-start",
1528 [JOB_RESTART] = "restart",
1529 [JOB_TRY_RESTART] = "try-restart",
3282591d 1530 [JOB_TRY_RELOAD] = "try-reload",
e0209d83 1531 [JOB_NOP] = "nop",
94f04347
LP
1532};
1533
1534DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
b548631a
LP
1535
1536static const char* const job_mode_table[_JOB_MODE_MAX] = {
1537 [JOB_FAIL] = "fail",
c497c7a9 1538 [JOB_REPLACE] = "replace",
23ade460 1539 [JOB_REPLACE_IRREVERSIBLY] = "replace-irreversibly",
e67c3609 1540 [JOB_ISOLATE] = "isolate",
2c5859af 1541 [JOB_FLUSH] = "flush",
cebe0d41 1542 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
255baef6 1543 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements",
b548631a
LP
1544};
1545
1546DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
5d44db4a
LP
1547
1548static const char* const job_result_table[_JOB_RESULT_MAX] = {
1549 [JOB_DONE] = "done",
1550 [JOB_CANCELED] = "canceled",
1551 [JOB_TIMEOUT] = "timeout",
1552 [JOB_FAILED] = "failed",
d68201e9 1553 [JOB_DEPENDENCY] = "dependency",
6a371e23
ZJS
1554 [JOB_SKIPPED] = "skipped",
1555 [JOB_INVALID] = "invalid",
59fccdc5 1556 [JOB_ASSERT] = "assert",
0faacd47 1557 [JOB_UNSUPPORTED] = "unsupported",
c5a97ed1 1558 [JOB_COLLECTED] = "collected",
d4fd1cf2 1559 [JOB_ONCE] = "once",
5d44db4a
LP
1560};
1561
1562DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);
94bd7323
EV
1563
1564const char* job_type_to_access_method(JobType t) {
1565 assert(t >= 0);
1566 assert(t < _JOB_TYPE_MAX);
1567
1568 if (IN_SET(t, JOB_START, JOB_RESTART, JOB_TRY_RESTART))
1569 return "start";
1570 else if (t == JOB_STOP)
1571 return "stop";
1572 else
1573 return "reload";
1574}