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