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