Coverage Report

Created: 2019-06-19 13:33

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