]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/job.c
vconsole: use /dev/vcsa1-15 to check for allocated VTs
[thirdparty/systemd.git] / src / core / job.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60918275 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
60918275 22#include <assert.h>
1ffba6fe 23#include <errno.h>
faf919f1
LP
24#include <sys/timerfd.h>
25#include <sys/epoll.h>
60918275 26
877d54e9
LP
27#include "systemd/sd-id128.h"
28#include "systemd/sd-messages.h"
94f04347
LP
29#include "set.h"
30#include "unit.h"
60918275 31#include "macro.h"
94f04347
LP
32#include "strv.h"
33#include "load-fragment.h"
34#include "load-dropin.h"
f50e0a01 35#include "log.h"
4139c1b2 36#include "dbus-job.h"
60918275 37
97e6a119
MS
38JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
39 JobBusClient *cl;
40 size_t name_len;
41
42 name_len = strlen(name);
43 cl = malloc0(sizeof(JobBusClient) + name_len + 1);
44 if (!cl)
45 return NULL;
46
47 cl->bus = connection;
48 memcpy(cl->name, name, name_len + 1);
49 return cl;
50}
51
39a18c60 52Job* job_new_raw(Unit *unit) {
60918275
LP
53 Job *j;
54
39a18c60
MS
55 /* used for deserialization */
56
87f0e418 57 assert(unit);
60918275 58
39a18c60
MS
59 j = new0(Job, 1);
60 if (!j)
60918275
LP
61 return NULL;
62
668ad332 63 j->manager = unit->manager;
87f0e418 64 j->unit = unit;
e0209d83 65 j->type = _JOB_TYPE_INVALID;
faf919f1
LP
66 j->timer_watch.type = WATCH_INVALID;
67
39a18c60
MS
68 return j;
69}
70
71Job* job_new(Unit *unit, JobType type) {
72 Job *j;
73
74 assert(type < _JOB_TYPE_MAX);
75
76 j = job_new_raw(unit);
77 if (!j)
78 return NULL;
79
80 j->id = j->manager->current_job_id++;
81 j->type = type;
82
e5b5ae50 83 /* We don't link it here, that's what job_dependency() is for */
60918275
LP
84
85 return j;
86}
87
97e7d748 88void job_free(Job *j) {
97e6a119
MS
89 JobBusClient *cl;
90
97e7d748
MS
91 assert(j);
92 assert(!j->installed);
02a3bcc6
MS
93 assert(!j->transaction_prev);
94 assert(!j->transaction_next);
95 assert(!j->subject_list);
96 assert(!j->object_list);
60918275 97
c1e1601e
LP
98 if (j->in_run_queue)
99 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
100
101 if (j->in_dbus_queue)
102 LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
103
faf919f1
LP
104 if (j->timer_watch.type != WATCH_INVALID) {
105 assert(j->timer_watch.type == WATCH_JOB_TIMER);
106 assert(j->timer_watch.data.job == j);
107 assert(j->timer_watch.fd >= 0);
108
109 assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
110 close_nointr_nofail(j->timer_watch.fd);
111 }
112
97e6a119
MS
113 while ((cl = j->bus_client_list)) {
114 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
115 free(cl);
116 }
60918275
LP
117 free(j);
118}
a66d02c3 119
05d576f1 120void job_uninstall(Job *j) {
e0209d83
MS
121 Job **pj;
122
05d576f1 123 assert(j->installed);
e0209d83
MS
124
125 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
126 assert(*pj == j);
127
05d576f1
MS
128 /* Detach from next 'bigger' objects */
129
39a18c60
MS
130 /* daemon-reload should be transparent to job observers */
131 if (j->manager->n_reloading <= 0)
132 bus_job_send_removed_signal(j);
05d576f1 133
e0209d83
MS
134 *pj = NULL;
135
d6a093d0 136 unit_add_to_gc_queue(j->unit);
05d576f1
MS
137
138 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
139 j->installed = false;
140}
141
656bbffc
MS
142static bool job_type_allows_late_merge(JobType t) {
143 /* Tells whether it is OK to merge a job of type 't' with an already
144 * running job.
145 * Reloads cannot be merged this way. Think of the sequence:
146 * 1. Reload of a daemon is in progress; the daemon has already loaded
147 * its config file, but hasn't completed the reload operation yet.
148 * 2. Edit foo's config file.
149 * 3. Trigger another reload to have the daemon use the new config.
150 * Should the second reload job be merged into the first one, the daemon
151 * would not know about the new config.
152 * JOB_RESTART jobs on the other hand can be merged, because they get
153 * patched into JOB_START after stopping the unit. So if we see a
154 * JOB_RESTART running, it means the unit hasn't stopped yet and at
155 * this time the merge is still allowed. */
e0209d83 156 return t != JOB_RELOAD;
656bbffc
MS
157}
158
159static void job_merge_into_installed(Job *j, Job *other) {
160 assert(j->installed);
161 assert(j->unit == other->unit);
162
e0209d83
MS
163 if (j->type != JOB_NOP)
164 job_type_merge_and_collapse(&j->type, other->type, j->unit);
165 else
166 assert(other->type == JOB_NOP);
656bbffc
MS
167
168 j->override = j->override || other->override;
169}
170
171Job* job_install(Job *j) {
e0209d83
MS
172 Job **pj;
173 Job *uj;
05d576f1 174
656bbffc 175 assert(!j->installed);
e0209d83
MS
176 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
177
178 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
179 uj = *pj;
656bbffc 180
05d576f1 181 if (uj) {
e0209d83 182 if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
1abc85b8 183 job_finish_and_invalidate(uj, JOB_CANCELED, false);
656bbffc
MS
184 else {
185 /* not conflicting, i.e. mergeable */
186
e0209d83 187 if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
656bbffc
MS
188 (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
189 job_merge_into_installed(uj, j);
66870f90
ZJS
190 log_debug_unit(uj->unit->id,
191 "Merged into installed job %s/%s as %u",
192 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
656bbffc
MS
193 return uj;
194 } else {
195 /* already running and not safe to merge into */
196 /* Patch uj to become a merged job and re-run it. */
197 /* XXX It should be safer to queue j to run after uj finishes, but it is
198 * not currently possible to have more than one installed job per unit. */
199 job_merge_into_installed(uj, j);
66870f90
ZJS
200 log_debug_unit(uj->unit->id,
201 "Merged into running job, re-running: %s/%s as %u",
202 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
656bbffc
MS
203 uj->state = JOB_WAITING;
204 return uj;
205 }
206 }
05d576f1
MS
207 }
208
656bbffc 209 /* Install the job */
e0209d83 210 *pj = j;
05d576f1
MS
211 j->installed = true;
212 j->manager->n_installed_jobs ++;
66870f90
ZJS
213 log_debug_unit(j->unit->id,
214 "Installed new job %s/%s as %u",
215 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
656bbffc 216 return j;
05d576f1
MS
217}
218
e0209d83
MS
219int job_install_deserialized(Job *j) {
220 Job **pj;
221
39a18c60
MS
222 assert(!j->installed);
223
e0209d83
MS
224 if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
225 log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
226 return -EINVAL;
227 }
228
229 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
230
231 if (*pj) {
66870f90
ZJS
232 log_debug_unit(j->unit->id,
233 "Unit %s already has a job installed. Not installing deserialized job.",
234 j->unit->id);
e0209d83 235 return -EEXIST;
39a18c60 236 }
e0209d83 237 *pj = j;
39a18c60 238 j->installed = true;
66870f90
ZJS
239 log_debug_unit(j->unit->id,
240 "Reinstalled deserialized job %s/%s as %u",
241 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
e0209d83 242 return 0;
39a18c60
MS
243}
244
1da4264f 245JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
e5b5ae50
LP
246 JobDependency *l;
247
248 assert(object);
249
250 /* Adds a new job link, which encodes that the 'subject' job
251 * needs the 'object' job in some way. If 'subject' is NULL
252 * this means the 'anchor' job (i.e. the one the user
35b8ca3a 253 * explicitly asked for) is the requester. */
e5b5ae50 254
ceed3570 255 if (!(l = new0(JobDependency, 1)))
e5b5ae50
LP
256 return NULL;
257
258 l->subject = subject;
259 l->object = object;
260 l->matters = matters;
69dd2852 261 l->conflicts = conflicts;
e5b5ae50 262
44d8db9e
LP
263 if (subject)
264 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
e5b5ae50 265
44d8db9e 266 LIST_PREPEND(JobDependency, object, object->object_list, l);
e5b5ae50
LP
267
268 return l;
269}
270
1da4264f 271void job_dependency_free(JobDependency *l) {
e5b5ae50
LP
272 assert(l);
273
44d8db9e
LP
274 if (l->subject)
275 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
e5b5ae50 276
44d8db9e 277 LIST_REMOVE(JobDependency, object, l->object->object_list, l);
e5b5ae50
LP
278
279 free(l);
280}
281
1ffba6fe 282void job_dump(Job *j, FILE*f, const char *prefix) {
a66d02c3
LP
283 assert(j);
284 assert(f);
285
9eb63b3c
LP
286 if (!prefix)
287 prefix = "";
288
ceed3570 289 fprintf(f,
40d50879
LP
290 "%s-> Job %u:\n"
291 "%s\tAction: %s -> %s\n"
5cb5a6ff
LP
292 "%s\tState: %s\n"
293 "%s\tForced: %s\n",
ceed3570 294 prefix, j->id,
ac155bb8 295 prefix, j->unit->id, job_type_to_string(j->type),
94f04347 296 prefix, job_state_to_string(j->state),
9e2f7c11 297 prefix, yes_no(j->override));
a66d02c3 298}
e5b5ae50 299
348e27fe
MS
300/*
301 * Merging is commutative, so imagine the matrix as symmetric. We store only
302 * its lower triangle to avoid duplication. We don't store the main diagonal,
303 * because A merged with A is simply A.
304 *
e0209d83
MS
305 * If the resulting type is collapsed immediately afterwards (to get rid of
306 * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
307 * the following properties hold:
308 *
348e27fe
MS
309 * Merging is associative! A merged with B merged with C is the same as
310 * A merged with C merged with B.
311 *
312 * Mergeability is transitive! If A can be merged with B and B with C then
313 * A also with C.
314 *
315 * Also, if A merged with B cannot be merged with C, then either A or B cannot
316 * be merged with C either.
317 */
318static const JobType job_merging_table[] = {
e0209d83
MS
319/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
320/*********************************************************************************/
348e27fe
MS
321/*JOB_START */
322/*JOB_VERIFY_ACTIVE */ JOB_START,
323/*JOB_STOP */ -1, -1,
324/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
e0209d83 325/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
348e27fe
MS
326};
327
328JobType job_type_lookup_merge(JobType a, JobType b) {
e0209d83
MS
329 assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
330 assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
331 assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
1ffba6fe
LP
332
333 if (a == b)
348e27fe 334 return a;
1ffba6fe 335
348e27fe
MS
336 if (a < b) {
337 JobType tmp = a;
338 a = b;
339 b = tmp;
1ffba6fe 340 }
e094e853 341
348e27fe 342 return job_merging_table[(a - 1) * a / 2 + b];
e094e853 343}
cd2dbd7d 344
593fbdd2
LP
345bool job_type_is_redundant(JobType a, UnitActiveState b) {
346 switch (a) {
347
348 case JOB_START:
349 return
350 b == UNIT_ACTIVE ||
032ff4af 351 b == UNIT_RELOADING;
593fbdd2
LP
352
353 case JOB_STOP:
354 return
6124958c 355 b == UNIT_INACTIVE ||
fdf20a31 356 b == UNIT_FAILED;
593fbdd2
LP
357
358 case JOB_VERIFY_ACTIVE:
359 return
360 b == UNIT_ACTIVE ||
032ff4af 361 b == UNIT_RELOADING;
593fbdd2
LP
362
363 case JOB_RELOAD:
364 return
032ff4af 365 b == UNIT_RELOADING;
593fbdd2 366
593fbdd2
LP
367 case JOB_RESTART:
368 return
369 b == UNIT_ACTIVATING;
370
e0209d83
MS
371 default:
372 assert_not_reached("Invalid job type");
373 }
374}
375
376void job_type_collapse(JobType *t, Unit *u) {
377 UnitActiveState s;
378
379 switch (*t) {
380
593fbdd2 381 case JOB_TRY_RESTART:
e0209d83
MS
382 s = unit_active_state(u);
383 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
384 *t = JOB_NOP;
385 else
386 *t = JOB_RESTART;
387 break;
388
389 case JOB_RELOAD_OR_START:
390 s = unit_active_state(u);
391 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
392 *t = JOB_START;
393 else
394 *t = JOB_RELOAD;
395 break;
593fbdd2
LP
396
397 default:
e0209d83 398 ;
593fbdd2
LP
399 }
400}
401
e0209d83
MS
402int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
403 JobType t = job_type_lookup_merge(*a, b);
404 if (t < 0)
405 return -EEXIST;
406 *a = t;
407 job_type_collapse(a, u);
408 return 0;
409}
410
5cb5a6ff 411bool job_is_runnable(Job *j) {
034c6ed7 412 Iterator i;
87f0e418 413 Unit *other;
5cb5a6ff
LP
414
415 assert(j);
ac1135be 416 assert(j->installed);
5cb5a6ff 417
87f0e418 418 /* Checks whether there is any job running for the units this
5cb5a6ff 419 * job needs to be running after (in the case of a 'positive'
e67c3609
LP
420 * job type) or before (in the case of a 'negative' job
421 * type. */
422
423 /* First check if there is an override */
cebe0d41 424 if (j->ignore_order)
e67c3609 425 return true;
5cb5a6ff 426
e0209d83
MS
427 if (j->type == JOB_NOP)
428 return true;
429
5cb5a6ff
LP
430 if (j->type == JOB_START ||
431 j->type == JOB_VERIFY_ACTIVE ||
e0209d83 432 j->type == JOB_RELOAD) {
5cb5a6ff
LP
433
434 /* Immediate result is that the job is or might be
435 * started. In this case lets wait for the
436 * dependencies, regardless whether they are
437 * starting or stopping something. */
438
ac155bb8
MS
439 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
440 if (other->job)
5cb5a6ff
LP
441 return false;
442 }
443
444 /* Also, if something else is being stopped and we should
445 * change state after it, then lets wait. */
446
ac155bb8
MS
447 SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
448 if (other->job &&
449 (other->job->type == JOB_STOP ||
e0209d83 450 other->job->type == JOB_RESTART))
5cb5a6ff
LP
451 return false;
452
453 /* This means that for a service a and a service b where b
454 * shall be started after a:
455 *
456 * start a + start b → 1st step start a, 2nd step start b
457 * start a + stop b → 1st step stop b, 2nd step start a
458 * stop a + start b → 1st step stop a, 2nd step start b
459 * stop a + stop b → 1st step stop b, 2nd step stop a
460 *
461 * This has the side effect that restarts are properly
462 * synchronized too. */
463
464 return true;
465}
466
bbd1a837 467static void job_change_type(Job *j, JobType newtype) {
66870f90
ZJS
468 log_debug_unit(j->unit->id,
469 "Converting job %s/%s -> %s/%s",
470 j->unit->id, job_type_to_string(j->type),
471 j->unit->id, job_type_to_string(newtype));
bbd1a837
MS
472
473 j->type = newtype;
474}
475
5cb5a6ff
LP
476int job_run_and_invalidate(Job *j) {
477 int r;
2cf19a7a
LP
478 uint32_t id;
479 Manager *m;
ac1135be 480
5cb5a6ff 481 assert(j);
ac1135be 482 assert(j->installed);
e0209d83 483 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
66aa6f7f 484 assert(j->in_run_queue);
5cb5a6ff 485
66aa6f7f
MS
486 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
487 j->in_run_queue = false;
5cb5a6ff
LP
488
489 if (j->state != JOB_WAITING)
490 return 0;
491
034c6ed7
LP
492 if (!job_is_runnable(j))
493 return -EAGAIN;
494
83c60c9f 495 j->state = JOB_RUNNING;
c1e1601e 496 job_add_to_dbus_queue(j);
83c60c9f 497
2cf19a7a
LP
498 /* While we execute this operation the job might go away (for
499 * example: because it is replaced by a new, conflicting
500 * job.) To make sure we don't access a freed job later on we
501 * store the id here, so that we can verify the job is still
502 * valid. */
503 id = j->id;
504 m = j->manager;
505
5cb5a6ff
LP
506 switch (j->type) {
507
508 case JOB_START:
87f0e418 509 r = unit_start(j->unit);
57339f47 510
dd17d388 511 /* If this unit cannot be started, then simply wait */
5cb5a6ff
LP
512 if (r == -EBADR)
513 r = 0;
514 break;
515
516 case JOB_VERIFY_ACTIVE: {
87f0e418
LP
517 UnitActiveState t = unit_active_state(j->unit);
518 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
5cb5a6ff 519 r = -EALREADY;
87f0e418 520 else if (t == UNIT_ACTIVATING)
5cb5a6ff
LP
521 r = -EAGAIN;
522 else
523 r = -ENOEXEC;
524 break;
525 }
526
527 case JOB_STOP:
dd17d388 528 case JOB_RESTART:
87f0e418 529 r = unit_stop(j->unit);
57339f47 530
dd17d388 531 /* If this unit cannot stopped, then simply wait. */
57339f47
LP
532 if (r == -EBADR)
533 r = 0;
5cb5a6ff
LP
534 break;
535
536 case JOB_RELOAD:
87f0e418 537 r = unit_reload(j->unit);
5cb5a6ff
LP
538 break;
539
e0209d83
MS
540 case JOB_NOP:
541 r = -EALREADY;
542 break;
543
5cb5a6ff 544 default:
44d8db9e 545 assert_not_reached("Unknown job type");
5cb5a6ff
LP
546 }
547
e0209d83
MS
548 j = manager_get_job(m, id);
549 if (j) {
2cf19a7a 550 if (r == -EALREADY)
5273510e 551 r = job_finish_and_invalidate(j, JOB_DONE, true);
d68201e9 552 else if (r == -ENOEXEC)
5273510e 553 r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
2cf19a7a
LP
554 else if (r == -EAGAIN)
555 j->state = JOB_WAITING;
556 else if (r < 0)
5273510e 557 r = job_finish_and_invalidate(j, JOB_FAILED, true);
2cf19a7a 558 }
5cb5a6ff
LP
559
560 return r;
561}
562
877d54e9 563static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
c6918296 564 const UnitStatusMessageFormats *format_table;
877d54e9
LP
565
566 assert(u);
567 assert(t >= 0);
568 assert(t < _JOB_TYPE_MAX);
c6918296
MS
569
570 format_table = &UNIT_VTABLE(u)->status_message_formats;
571 if (!format_table)
877d54e9
LP
572 return NULL;
573
574 if (t == JOB_START)
575 return format_table->finished_start_job[result];
576 else if (t == JOB_STOP || t == JOB_RESTART)
577 return format_table->finished_stop_job[result];
578
579 return NULL;
580}
e02cd6f7 581
877d54e9
LP
582static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
583 const char *format;
584
585 assert(u);
586 assert(t >= 0);
587 assert(t < _JOB_TYPE_MAX);
588
589 format = job_get_status_message_format(u, t, result);
590 if (format)
591 return format;
592
593 /* Return generic strings */
e02cd6f7 594 if (t == JOB_START) {
877d54e9
LP
595 if (result == JOB_DONE)
596 return "Started %s.";
597 else if (result == JOB_FAILED)
598 return "Failed to start %s.";
599 else if (result == JOB_DEPENDENCY)
600 return "Dependency failed for %s.";
601 else if (result == JOB_TIMEOUT)
602 return "Timed out starting %s.";
603 } else if (t == JOB_STOP || t == JOB_RESTART) {
604 if (result == JOB_DONE)
605 return "Stopped %s.";
606 else if (result == JOB_FAILED)
607 return "Stopped (with error) %s.";
608 else if (result == JOB_TIMEOUT)
609 return "Timed out stoppping %s.";
610 } else if (t == JOB_RELOAD) {
611 if (result == JOB_DONE)
612 return "Reloaded %s.";
613 else if (result == JOB_FAILED)
614 return "Reload failed for %s.";
615 else if (result == JOB_TIMEOUT)
616 return "Timed out reloading %s.";
617 }
618
619 return NULL;
620}
621
622static void job_print_status_message(Unit *u, JobType t, JobResult result) {
623 const char *format;
e02cd6f7 624
877d54e9
LP
625 assert(u);
626 assert(t >= 0);
627 assert(t < _JOB_TYPE_MAX);
628
629 if (t == JOB_START) {
630 format = job_get_status_message_format(u, t, result);
c6918296
MS
631 if (!format)
632 return;
633
e02cd6f7
LP
634 switch (result) {
635
636 case JOB_DONE:
69120666 637 if (u->condition_result)
c6918296 638 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
639 break;
640
641 case JOB_FAILED:
c6918296 642 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
877d54e9 643 unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
e02cd6f7
LP
644 break;
645
646 case JOB_DEPENDENCY:
c6918296 647 unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
648 break;
649
650 case JOB_TIMEOUT:
c6918296 651 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
652 break;
653
654 default:
655 ;
656 }
657
1f136e7a 658 } else if (t == JOB_STOP || t == JOB_RESTART) {
e02cd6f7 659
877d54e9 660 format = job_get_status_message_format(u, t, result);
c6918296
MS
661 if (!format)
662 return;
663
e02cd6f7
LP
664 switch (result) {
665
666 case JOB_TIMEOUT:
c6918296 667 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
668 break;
669
670 case JOB_DONE:
671 case JOB_FAILED:
c6918296 672 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
e02cd6f7
LP
673 break;
674
675 default:
676 ;
677 }
7cf82e0b
MS
678
679 } else if (t == JOB_VERIFY_ACTIVE) {
680
681 /* When verify-active detects the unit is inactive, report it.
682 * Most likely a DEPEND warning from a requisiting unit will
683 * occur next and it's nice to see what was requisited. */
684 if (result == JOB_SKIPPED)
685 unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.", unit_description(u));
e02cd6f7
LP
686 }
687}
688
877d54e9
LP
689#pragma GCC diagnostic push
690#pragma GCC diagnostic ignored "-Wformat-nonliteral"
691static void job_log_status_message(Unit *u, JobType t, JobResult result) {
692 const char *format;
693 char buf[LINE_MAX];
694
695 assert(u);
696 assert(t >= 0);
697 assert(t < _JOB_TYPE_MAX);
698
81270860
LP
699 /* Skip this if it goes to the console. since we already print
700 * to the console anyway... */
701
702 if (log_on_console())
703 return;
704
877d54e9
LP
705 format = job_get_status_message_format_try_harder(u, t, result);
706 if (!format)
707 return;
708
709 snprintf(buf, sizeof(buf), format, unit_description(u));
710 char_array_0(buf);
711
712 if (t == JOB_START) {
713 sd_id128_t mid;
714
715 mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
716 log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
1ca6783f 717 MESSAGE_ID(mid),
877d54e9
LP
718 "UNIT=%s", u->id,
719 "RESULT=%s", job_result_to_string(result),
720 "MESSAGE=%s", buf,
721 NULL);
722
723 } else if (t == JOB_STOP)
724 log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
1ca6783f 725 MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
877d54e9
LP
726 "UNIT=%s", u->id,
727 "RESULT=%s", job_result_to_string(result),
728 "MESSAGE=%s", buf,
729 NULL);
730
731 else if (t == JOB_RELOAD)
732 log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
1ca6783f 733 MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
877d54e9
LP
734 "UNIT=%s", u->id,
735 "RESULT=%s", job_result_to_string(result),
736 "MESSAGE=%s", buf,
737 NULL);
738}
739#pragma GCC diagnostic pop
740
5273510e 741int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
87f0e418
LP
742 Unit *u;
743 Unit *other;
b866264a 744 JobType t;
034c6ed7 745 Iterator i;
5cb5a6ff
LP
746
747 assert(j);
ac1135be 748 assert(j->installed);
e0209d83 749 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
5cb5a6ff 750
c6918296
MS
751 u = j->unit;
752 t = j->type;
753
754 j->result = result;
755
66870f90
ZJS
756 log_debug_unit(u->id, "Job %s/%s finished, result=%s",
757 u->id, job_type_to_string(t), job_result_to_string(result));
c6918296
MS
758
759 job_print_status_message(u, t, result);
877d54e9 760 job_log_status_message(u, t, result);
c6918296 761
c1e1601e 762 job_add_to_dbus_queue(j);
f50e0a01 763
034c6ed7 764 /* Patch restart jobs so that they become normal start jobs */
c6918296 765 if (result == JOB_DONE && t == JOB_RESTART) {
f50e0a01 766
bbd1a837 767 job_change_type(j, JOB_START);
9c2d9caa 768 j->state = JOB_WAITING;
cc42e081
LP
769
770 job_add_to_run_queue(j);
57981b98 771
57981b98 772 goto finish;
5cb5a6ff
LP
773 }
774
5d44db4a 775 if (result == JOB_FAILED)
76bf48b7
LP
776 j->manager->n_failed_jobs ++;
777
97e7d748 778 job_uninstall(j);
5cb5a6ff
LP
779 job_free(j);
780
781 /* Fail depending jobs on failure */
5273510e 782 if (result != JOB_DONE && recursive) {
5cb5a6ff
LP
783
784 if (t == JOB_START ||
e0209d83 785 t == JOB_VERIFY_ACTIVE) {
5cb5a6ff 786
ac155bb8
MS
787 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
788 if (other->job &&
789 (other->job->type == JOB_START ||
e0209d83 790 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 791 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
5cb5a6ff 792
ac155bb8
MS
793 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
794 if (other->job &&
795 (other->job->type == JOB_START ||
e0209d83 796 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 797 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
e6a3ff95 798
ac155bb8
MS
799 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
800 if (other->job &&
801 !other->job->override &&
802 (other->job->type == JOB_START ||
e0209d83 803 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 804 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
5cb5a6ff
LP
805
806 } else if (t == JOB_STOP) {
807
ac155bb8
MS
808 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
809 if (other->job &&
810 (other->job->type == JOB_START ||
e0209d83 811 other->job->type == JOB_VERIFY_ACTIVE))
5273510e 812 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
5cb5a6ff
LP
813 }
814 }
815
c0daa706 816 /* Trigger OnFailure dependencies that are not generated by
66870f90 817 * the unit itself. We don't treat JOB_CANCELED as failure in
c0daa706
LP
818 * this context. And JOB_FAILURE is already handled by the
819 * unit itself. */
222ae6a8 820 if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
66870f90
ZJS
821 log_struct(LOG_NOTICE,
822 "UNIT=%s", u->id,
823 "JOB_TYPE=%s", job_type_to_string(t),
824 "JOB_RESULT=%s", job_result_to_string(t),
825 "Job %s/%s failed with result '%s'.",
ac155bb8 826 u->id,
222ae6a8 827 job_type_to_string(t),
66870f90
ZJS
828 job_result_to_string(result),
829 NULL);
222ae6a8 830
c0daa706 831 unit_trigger_on_failure(u);
222ae6a8 832 }
c0daa706 833
57981b98 834finish:
5cb5a6ff 835 /* Try to start the next jobs that can be started */
ac155bb8
MS
836 SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
837 if (other->job)
838 job_add_to_run_queue(other->job);
839 SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
840 if (other->job)
841 job_add_to_run_queue(other->job);
5cb5a6ff 842
ac155bb8 843 manager_check_finished(u->manager);
b0c918b9 844
5273510e 845 return 0;
5cb5a6ff 846}
034c6ed7 847
faf919f1
LP
848int job_start_timer(Job *j) {
849 struct itimerspec its;
850 struct epoll_event ev;
851 int fd, r;
852 assert(j);
853
ac155bb8 854 if (j->unit->job_timeout <= 0 ||
faf919f1
LP
855 j->timer_watch.type == WATCH_JOB_TIMER)
856 return 0;
857
858 assert(j->timer_watch.type == WATCH_INVALID);
859
860 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
861 r = -errno;
862 goto fail;
863 }
864
865 zero(its);
ac155bb8 866 timespec_store(&its.it_value, j->unit->job_timeout);
faf919f1
LP
867
868 if (timerfd_settime(fd, 0, &its, NULL) < 0) {
869 r = -errno;
870 goto fail;
871 }
872
873 zero(ev);
874 ev.data.ptr = &j->timer_watch;
875 ev.events = EPOLLIN;
876
877 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
878 r = -errno;
879 goto fail;
880 }
881
882 j->timer_watch.type = WATCH_JOB_TIMER;
883 j->timer_watch.fd = fd;
884 j->timer_watch.data.job = j;
885
886 return 0;
887
888fail:
889 if (fd >= 0)
890 close_nointr_nofail(fd);
891
892 return r;
893}
894
c1e1601e 895void job_add_to_run_queue(Job *j) {
034c6ed7 896 assert(j);
ac1135be 897 assert(j->installed);
034c6ed7
LP
898
899 if (j->in_run_queue)
900 return;
901
902 LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
903 j->in_run_queue = true;
904}
94f04347 905
c1e1601e
LP
906void job_add_to_dbus_queue(Job *j) {
907 assert(j);
908 assert(j->installed);
909
910 if (j->in_dbus_queue)
911 return;
912
a567261a
LP
913 /* We don't check if anybody is subscribed here, since this
914 * job might just have been created and not yet assigned to a
915 * connection/client. */
94b6dfa2 916
c1e1601e
LP
917 LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
918 j->in_dbus_queue = true;
919}
920
ea430986
LP
921char *job_dbus_path(Job *j) {
922 char *p;
923
924 assert(j);
925
926 if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
927 return NULL;
928
929 return p;
930}
931
faf919f1
LP
932void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
933 assert(j);
934 assert(w == &j->timer_watch);
935
66870f90
ZJS
936 log_warning_unit(j->unit->id, "Job %s/%s timed out.",
937 j->unit->id, job_type_to_string(j->type));
5273510e 938 job_finish_and_invalidate(j, JOB_TIMEOUT, true);
faf919f1
LP
939}
940
39a18c60
MS
941int job_serialize(Job *j, FILE *f, FDSet *fds) {
942 fprintf(f, "job-id=%u\n", j->id);
943 fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
944 fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
945 fprintf(f, "job-override=%s\n", yes_no(j->override));
946 fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
947 fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
948 /* Cannot save bus clients. Just note the fact that we're losing
949 * them. job_send_message() will fallback to broadcasting. */
950 fprintf(f, "job-forgot-bus-clients=%s\n",
951 yes_no(j->forgot_bus_clients || j->bus_client_list));
952 if (j->timer_watch.type == WATCH_JOB_TIMER) {
953 int copy = fdset_put_dup(fds, j->timer_watch.fd);
954 if (copy < 0)
955 return copy;
956 fprintf(f, "job-timer-watch-fd=%d\n", copy);
957 }
958
959 /* End marker */
960 fputc('\n', f);
961 return 0;
962}
963
964int job_deserialize(Job *j, FILE *f, FDSet *fds) {
965 for (;;) {
966 char line[LINE_MAX], *l, *v;
967 size_t k;
968
969 if (!fgets(line, sizeof(line), f)) {
970 if (feof(f))
971 return 0;
972 return -errno;
973 }
974
975 char_array_0(line);
976 l = strstrip(line);
977
978 /* End marker */
979 if (l[0] == 0)
980 return 0;
981
982 k = strcspn(l, "=");
983
984 if (l[k] == '=') {
985 l[k] = 0;
986 v = l+k+1;
987 } else
988 v = l+k;
989
990 if (streq(l, "job-id")) {
991 if (safe_atou32(v, &j->id) < 0)
992 log_debug("Failed to parse job id value %s", v);
993 } else if (streq(l, "job-type")) {
994 JobType t = job_type_from_string(v);
995 if (t < 0)
996 log_debug("Failed to parse job type %s", v);
e0209d83
MS
997 else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
998 log_debug("Cannot deserialize job of type %s", v);
39a18c60
MS
999 else
1000 j->type = t;
1001 } else if (streq(l, "job-state")) {
1002 JobState s = job_state_from_string(v);
1003 if (s < 0)
1004 log_debug("Failed to parse job state %s", v);
1005 else
1006 j->state = s;
1007 } else if (streq(l, "job-override")) {
1008 int b = parse_boolean(v);
1009 if (b < 0)
1010 log_debug("Failed to parse job override flag %s", v);
1011 else
1012 j->override = j->override || b;
1013 } else if (streq(l, "job-sent-dbus-new-signal")) {
1014 int b = parse_boolean(v);
1015 if (b < 0)
1016 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
1017 else
1018 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
1019 } else if (streq(l, "job-ignore-order")) {
1020 int b = parse_boolean(v);
1021 if (b < 0)
1022 log_debug("Failed to parse job ignore_order flag %s", v);
1023 else
1024 j->ignore_order = j->ignore_order || b;
1025 } else if (streq(l, "job-forgot-bus-clients")) {
1026 int b = parse_boolean(v);
1027 if (b < 0)
1028 log_debug("Failed to parse job forgot_bus_clients flag %s", v);
1029 else
1030 j->forgot_bus_clients = j->forgot_bus_clients || b;
1031 } else if (streq(l, "job-timer-watch-fd")) {
1032 int fd;
1033 if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
1034 log_debug("Failed to parse job-timer-watch-fd value %s", v);
1035 else {
1036 if (j->timer_watch.type == WATCH_JOB_TIMER)
1037 close_nointr_nofail(j->timer_watch.fd);
1038
1039 j->timer_watch.type = WATCH_JOB_TIMER;
1040 j->timer_watch.fd = fdset_remove(fds, fd);
1041 j->timer_watch.data.job = j;
1042 }
1043 }
1044 }
1045}
1046
1047int job_coldplug(Job *j) {
1048 struct epoll_event ev;
1049
1050 if (j->timer_watch.type != WATCH_JOB_TIMER)
1051 return 0;
1052
1053 zero(ev);
1054 ev.data.ptr = &j->timer_watch;
1055 ev.events = EPOLLIN;
1056
1057 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
1058 return -errno;
1059
1060 return 0;
1061}
1062
94f04347
LP
1063static const char* const job_state_table[_JOB_STATE_MAX] = {
1064 [JOB_WAITING] = "waiting",
1065 [JOB_RUNNING] = "running"
1066};
1067
1068DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
1069
1070static const char* const job_type_table[_JOB_TYPE_MAX] = {
1071 [JOB_START] = "start",
1072 [JOB_VERIFY_ACTIVE] = "verify-active",
1073 [JOB_STOP] = "stop",
1074 [JOB_RELOAD] = "reload",
1075 [JOB_RELOAD_OR_START] = "reload-or-start",
1076 [JOB_RESTART] = "restart",
1077 [JOB_TRY_RESTART] = "try-restart",
e0209d83 1078 [JOB_NOP] = "nop",
94f04347
LP
1079};
1080
1081DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
b548631a
LP
1082
1083static const char* const job_mode_table[_JOB_MODE_MAX] = {
1084 [JOB_FAIL] = "fail",
c497c7a9 1085 [JOB_REPLACE] = "replace",
e67c3609 1086 [JOB_ISOLATE] = "isolate",
cebe0d41
LP
1087 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
1088 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
b548631a
LP
1089};
1090
1091DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
5d44db4a
LP
1092
1093static const char* const job_result_table[_JOB_RESULT_MAX] = {
1094 [JOB_DONE] = "done",
1095 [JOB_CANCELED] = "canceled",
1096 [JOB_TIMEOUT] = "timeout",
1097 [JOB_FAILED] = "failed",
d68201e9
LP
1098 [JOB_DEPENDENCY] = "dependency",
1099 [JOB_SKIPPED] = "skipped"
5d44db4a
LP
1100};
1101
1102DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);