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