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