]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/job.c
job: info message if JOB_VERIFY_ACTIVE detects an inactive unit
[thirdparty/systemd.git] / src / core / job.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
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
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
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
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <assert.h>
23 #include <errno.h>
24 #include <sys/timerfd.h>
25 #include <sys/epoll.h>
26
27 #include "set.h"
28 #include "unit.h"
29 #include "macro.h"
30 #include "strv.h"
31 #include "load-fragment.h"
32 #include "load-dropin.h"
33 #include "log.h"
34 #include "dbus-job.h"
35
36 JobBusClient* 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
50 Job* job_new_raw(Unit *unit) {
51 Job *j;
52
53 /* used for deserialization */
54
55 assert(unit);
56
57 j = new0(Job, 1);
58 if (!j)
59 return NULL;
60
61 j->manager = unit->manager;
62 j->unit = unit;
63 j->type = _JOB_TYPE_INVALID;
64 j->timer_watch.type = WATCH_INVALID;
65
66 return j;
67 }
68
69 Job* 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
81 /* We don't link it here, that's what job_dependency() is for */
82
83 return j;
84 }
85
86 void job_free(Job *j) {
87 JobBusClient *cl;
88
89 assert(j);
90 assert(!j->installed);
91 assert(!j->transaction_prev);
92 assert(!j->transaction_next);
93 assert(!j->subject_list);
94 assert(!j->object_list);
95
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
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
111 while ((cl = j->bus_client_list)) {
112 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
113 free(cl);
114 }
115 free(j);
116 }
117
118 void job_uninstall(Job *j) {
119 Job **pj;
120
121 assert(j->installed);
122
123 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
124 assert(*pj == j);
125
126 /* Detach from next 'bigger' objects */
127
128 /* daemon-reload should be transparent to job observers */
129 if (j->manager->n_reloading <= 0)
130 bus_job_send_removed_signal(j);
131
132 *pj = NULL;
133
134 unit_add_to_gc_queue(j->unit);
135
136 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
137 j->installed = false;
138 }
139
140 static 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. */
154 return t != JOB_RELOAD;
155 }
156
157 static void job_merge_into_installed(Job *j, Job *other) {
158 assert(j->installed);
159 assert(j->unit == other->unit);
160
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);
165
166 j->override = j->override || other->override;
167 }
168
169 Job* job_install(Job *j) {
170 Job **pj;
171 Job *uj;
172
173 assert(!j->installed);
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;
178
179 if (uj) {
180 if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
181 job_finish_and_invalidate(uj, JOB_CANCELED, true);
182 else {
183 /* not conflicting, i.e. mergeable */
184
185 if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
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 }
203 }
204
205 /* Install the job */
206 *pj = j;
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);
210 return j;
211 }
212
213 int job_install_deserialized(Job *j) {
214 Job **pj;
215
216 assert(!j->installed);
217
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) {
226 log_debug("Unit %s already has a job installed. Not installing deserialized job.", j->unit->id);
227 return -EEXIST;
228 }
229 *pj = j;
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);
232 return 0;
233 }
234
235 JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
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
243 * explicitly asked for) is the requester. */
244
245 if (!(l = new0(JobDependency, 1)))
246 return NULL;
247
248 l->subject = subject;
249 l->object = object;
250 l->matters = matters;
251 l->conflicts = conflicts;
252
253 if (subject)
254 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
255
256 LIST_PREPEND(JobDependency, object, object->object_list, l);
257
258 return l;
259 }
260
261 void job_dependency_free(JobDependency *l) {
262 assert(l);
263
264 if (l->subject)
265 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
266
267 LIST_REMOVE(JobDependency, object, l->object->object_list, l);
268
269 free(l);
270 }
271
272 void job_dump(Job *j, FILE*f, const char *prefix) {
273 assert(j);
274 assert(f);
275
276 if (!prefix)
277 prefix = "";
278
279 fprintf(f,
280 "%s-> Job %u:\n"
281 "%s\tAction: %s -> %s\n"
282 "%s\tState: %s\n"
283 "%s\tForced: %s\n",
284 prefix, j->id,
285 prefix, j->unit->id, job_type_to_string(j->type),
286 prefix, job_state_to_string(j->state),
287 prefix, yes_no(j->override));
288 }
289
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 *
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 *
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 */
308 static const JobType job_merging_table[] = {
309 /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
310 /*********************************************************************************/
311 /*JOB_START */
312 /*JOB_VERIFY_ACTIVE */ JOB_START,
313 /*JOB_STOP */ -1, -1,
314 /*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
315 /*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
316 };
317
318 JobType job_type_lookup_merge(JobType a, JobType b) {
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);
322
323 if (a == b)
324 return a;
325
326 if (a < b) {
327 JobType tmp = a;
328 a = b;
329 b = tmp;
330 }
331
332 return job_merging_table[(a - 1) * a / 2 + b];
333 }
334
335 bool job_type_is_redundant(JobType a, UnitActiveState b) {
336 switch (a) {
337
338 case JOB_START:
339 return
340 b == UNIT_ACTIVE ||
341 b == UNIT_RELOADING;
342
343 case JOB_STOP:
344 return
345 b == UNIT_INACTIVE ||
346 b == UNIT_FAILED;
347
348 case JOB_VERIFY_ACTIVE:
349 return
350 b == UNIT_ACTIVE ||
351 b == UNIT_RELOADING;
352
353 case JOB_RELOAD:
354 return
355 b == UNIT_RELOADING;
356
357 case JOB_RESTART:
358 return
359 b == UNIT_ACTIVATING;
360
361 default:
362 assert_not_reached("Invalid job type");
363 }
364 }
365
366 void job_type_collapse(JobType *t, Unit *u) {
367 UnitActiveState s;
368
369 switch (*t) {
370
371 case JOB_TRY_RESTART:
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;
386
387 default:
388 ;
389 }
390 }
391
392 int 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
401 bool job_is_runnable(Job *j) {
402 Iterator i;
403 Unit *other;
404
405 assert(j);
406 assert(j->installed);
407
408 /* Checks whether there is any job running for the units this
409 * job needs to be running after (in the case of a 'positive'
410 * job type) or before (in the case of a 'negative' job
411 * type. */
412
413 /* First check if there is an override */
414 if (j->ignore_order)
415 return true;
416
417 if (j->type == JOB_NOP)
418 return true;
419
420 if (j->type == JOB_START ||
421 j->type == JOB_VERIFY_ACTIVE ||
422 j->type == JOB_RELOAD) {
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
429 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
430 if (other->job)
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
437 SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
438 if (other->job &&
439 (other->job->type == JOB_STOP ||
440 other->job->type == JOB_RESTART))
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
457 static 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
465 int job_run_and_invalidate(Job *j) {
466 int r;
467 uint32_t id;
468 Manager *m;
469
470 assert(j);
471 assert(j->installed);
472 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
473 assert(j->in_run_queue);
474
475 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
476 j->in_run_queue = false;
477
478 if (j->state != JOB_WAITING)
479 return 0;
480
481 if (!job_is_runnable(j))
482 return -EAGAIN;
483
484 j->state = JOB_RUNNING;
485 job_add_to_dbus_queue(j);
486
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
495 switch (j->type) {
496
497 case JOB_START:
498 r = unit_start(j->unit);
499
500 /* If this unit cannot be started, then simply wait */
501 if (r == -EBADR)
502 r = 0;
503 break;
504
505 case JOB_VERIFY_ACTIVE: {
506 UnitActiveState t = unit_active_state(j->unit);
507 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
508 r = -EALREADY;
509 else if (t == UNIT_ACTIVATING)
510 r = -EAGAIN;
511 else
512 r = -ENOEXEC;
513 break;
514 }
515
516 case JOB_STOP:
517 case JOB_RESTART:
518 r = unit_stop(j->unit);
519
520 /* If this unit cannot stopped, then simply wait. */
521 if (r == -EBADR)
522 r = 0;
523 break;
524
525 case JOB_RELOAD:
526 r = unit_reload(j->unit);
527 break;
528
529 case JOB_NOP:
530 r = -EALREADY;
531 break;
532
533 default:
534 assert_not_reached("Unknown job type");
535 }
536
537 j = manager_get_job(m, id);
538 if (j) {
539 if (r == -EALREADY)
540 r = job_finish_and_invalidate(j, JOB_DONE, true);
541 else if (r == -ENOEXEC)
542 r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
543 else if (r == -EAGAIN)
544 j->state = JOB_WAITING;
545 else if (r < 0)
546 r = job_finish_and_invalidate(j, JOB_FAILED, true);
547 }
548
549 return r;
550 }
551
552 static void job_print_status_message(Unit *u, JobType t, JobResult result) {
553 const UnitStatusMessageFormats *format_table;
554 const char *format;
555
556 format_table = &UNIT_VTABLE(u)->status_message_formats;
557 if (!format_table)
558 return;
559
560 if (t == JOB_START) {
561
562 format = format_table->finished_start_job[result];
563 if (!format)
564 return;
565
566 switch (result) {
567
568 case JOB_DONE:
569 if (u->condition_result)
570 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
571 break;
572
573 case JOB_FAILED:
574 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
575 unit_status_printf(u, "", "See 'systemctl status %s' for details.", u->id);
576 break;
577
578 case JOB_DEPENDENCY:
579 unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
580 break;
581
582 case JOB_TIMEOUT:
583 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
584 break;
585
586 default:
587 ;
588 }
589
590 } else if (t == JOB_STOP || t == JOB_RESTART) {
591
592 format = format_table->finished_stop_job[result];
593 if (!format)
594 return;
595
596 switch (result) {
597
598 case JOB_TIMEOUT:
599 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
600 break;
601
602 case JOB_DONE:
603 case JOB_FAILED:
604 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
605 break;
606
607 default:
608 ;
609 }
610
611 } else if (t == JOB_VERIFY_ACTIVE) {
612
613 /* When verify-active detects the unit is inactive, report it.
614 * Most likely a DEPEND warning from a requisiting unit will
615 * occur next and it's nice to see what was requisited. */
616 if (result == JOB_SKIPPED)
617 unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.", unit_description(u));
618 }
619 }
620
621 int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
622 Unit *u;
623 Unit *other;
624 JobType t;
625 Iterator i;
626
627 assert(j);
628 assert(j->installed);
629 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
630
631 u = j->unit;
632 t = j->type;
633
634 j->result = result;
635
636 log_debug("Job %s/%s finished, result=%s", u->id, job_type_to_string(t), job_result_to_string(result));
637
638 job_print_status_message(u, t, result);
639
640 job_add_to_dbus_queue(j);
641
642 /* Patch restart jobs so that they become normal start jobs */
643 if (result == JOB_DONE && t == JOB_RESTART) {
644
645 job_change_type(j, JOB_START);
646 j->state = JOB_WAITING;
647
648 job_add_to_run_queue(j);
649
650 goto finish;
651 }
652
653 if (result == JOB_FAILED)
654 j->manager->n_failed_jobs ++;
655
656 job_uninstall(j);
657 job_free(j);
658
659 /* Fail depending jobs on failure */
660 if (result != JOB_DONE && recursive) {
661
662 if (t == JOB_START ||
663 t == JOB_VERIFY_ACTIVE) {
664
665 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
666 if (other->job &&
667 (other->job->type == JOB_START ||
668 other->job->type == JOB_VERIFY_ACTIVE))
669 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
670
671 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
672 if (other->job &&
673 (other->job->type == JOB_START ||
674 other->job->type == JOB_VERIFY_ACTIVE))
675 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
676
677 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
678 if (other->job &&
679 !other->job->override &&
680 (other->job->type == JOB_START ||
681 other->job->type == JOB_VERIFY_ACTIVE))
682 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
683
684 } else if (t == JOB_STOP) {
685
686 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
687 if (other->job &&
688 (other->job->type == JOB_START ||
689 other->job->type == JOB_VERIFY_ACTIVE))
690 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
691 }
692 }
693
694 /* Trigger OnFailure dependencies that are not generated by
695 * the unit itself. We don't tread JOB_CANCELED as failure in
696 * this context. And JOB_FAILURE is already handled by the
697 * unit itself. */
698 if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
699 log_notice("Job %s/%s failed with result '%s'.",
700 u->id,
701 job_type_to_string(t),
702 job_result_to_string(result));
703
704 unit_trigger_on_failure(u);
705 }
706
707 finish:
708 /* Try to start the next jobs that can be started */
709 SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
710 if (other->job)
711 job_add_to_run_queue(other->job);
712 SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
713 if (other->job)
714 job_add_to_run_queue(other->job);
715
716 manager_check_finished(u->manager);
717
718 return 0;
719 }
720
721 int job_start_timer(Job *j) {
722 struct itimerspec its;
723 struct epoll_event ev;
724 int fd, r;
725 assert(j);
726
727 if (j->unit->job_timeout <= 0 ||
728 j->timer_watch.type == WATCH_JOB_TIMER)
729 return 0;
730
731 assert(j->timer_watch.type == WATCH_INVALID);
732
733 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
734 r = -errno;
735 goto fail;
736 }
737
738 zero(its);
739 timespec_store(&its.it_value, j->unit->job_timeout);
740
741 if (timerfd_settime(fd, 0, &its, NULL) < 0) {
742 r = -errno;
743 goto fail;
744 }
745
746 zero(ev);
747 ev.data.ptr = &j->timer_watch;
748 ev.events = EPOLLIN;
749
750 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
751 r = -errno;
752 goto fail;
753 }
754
755 j->timer_watch.type = WATCH_JOB_TIMER;
756 j->timer_watch.fd = fd;
757 j->timer_watch.data.job = j;
758
759 return 0;
760
761 fail:
762 if (fd >= 0)
763 close_nointr_nofail(fd);
764
765 return r;
766 }
767
768 void job_add_to_run_queue(Job *j) {
769 assert(j);
770 assert(j->installed);
771
772 if (j->in_run_queue)
773 return;
774
775 LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
776 j->in_run_queue = true;
777 }
778
779 void job_add_to_dbus_queue(Job *j) {
780 assert(j);
781 assert(j->installed);
782
783 if (j->in_dbus_queue)
784 return;
785
786 /* We don't check if anybody is subscribed here, since this
787 * job might just have been created and not yet assigned to a
788 * connection/client. */
789
790 LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
791 j->in_dbus_queue = true;
792 }
793
794 char *job_dbus_path(Job *j) {
795 char *p;
796
797 assert(j);
798
799 if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
800 return NULL;
801
802 return p;
803 }
804
805 void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
806 assert(j);
807 assert(w == &j->timer_watch);
808
809 log_warning("Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
810 job_finish_and_invalidate(j, JOB_TIMEOUT, true);
811 }
812
813 int job_serialize(Job *j, FILE *f, FDSet *fds) {
814 fprintf(f, "job-id=%u\n", j->id);
815 fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
816 fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
817 fprintf(f, "job-override=%s\n", yes_no(j->override));
818 fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
819 fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
820 /* Cannot save bus clients. Just note the fact that we're losing
821 * them. job_send_message() will fallback to broadcasting. */
822 fprintf(f, "job-forgot-bus-clients=%s\n",
823 yes_no(j->forgot_bus_clients || j->bus_client_list));
824 if (j->timer_watch.type == WATCH_JOB_TIMER) {
825 int copy = fdset_put_dup(fds, j->timer_watch.fd);
826 if (copy < 0)
827 return copy;
828 fprintf(f, "job-timer-watch-fd=%d\n", copy);
829 }
830
831 /* End marker */
832 fputc('\n', f);
833 return 0;
834 }
835
836 int job_deserialize(Job *j, FILE *f, FDSet *fds) {
837 for (;;) {
838 char line[LINE_MAX], *l, *v;
839 size_t k;
840
841 if (!fgets(line, sizeof(line), f)) {
842 if (feof(f))
843 return 0;
844 return -errno;
845 }
846
847 char_array_0(line);
848 l = strstrip(line);
849
850 /* End marker */
851 if (l[0] == 0)
852 return 0;
853
854 k = strcspn(l, "=");
855
856 if (l[k] == '=') {
857 l[k] = 0;
858 v = l+k+1;
859 } else
860 v = l+k;
861
862 if (streq(l, "job-id")) {
863 if (safe_atou32(v, &j->id) < 0)
864 log_debug("Failed to parse job id value %s", v);
865 } else if (streq(l, "job-type")) {
866 JobType t = job_type_from_string(v);
867 if (t < 0)
868 log_debug("Failed to parse job type %s", v);
869 else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
870 log_debug("Cannot deserialize job of type %s", v);
871 else
872 j->type = t;
873 } else if (streq(l, "job-state")) {
874 JobState s = job_state_from_string(v);
875 if (s < 0)
876 log_debug("Failed to parse job state %s", v);
877 else
878 j->state = s;
879 } else if (streq(l, "job-override")) {
880 int b = parse_boolean(v);
881 if (b < 0)
882 log_debug("Failed to parse job override flag %s", v);
883 else
884 j->override = j->override || b;
885 } else if (streq(l, "job-sent-dbus-new-signal")) {
886 int b = parse_boolean(v);
887 if (b < 0)
888 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
889 else
890 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
891 } else if (streq(l, "job-ignore-order")) {
892 int b = parse_boolean(v);
893 if (b < 0)
894 log_debug("Failed to parse job ignore_order flag %s", v);
895 else
896 j->ignore_order = j->ignore_order || b;
897 } else if (streq(l, "job-forgot-bus-clients")) {
898 int b = parse_boolean(v);
899 if (b < 0)
900 log_debug("Failed to parse job forgot_bus_clients flag %s", v);
901 else
902 j->forgot_bus_clients = j->forgot_bus_clients || b;
903 } else if (streq(l, "job-timer-watch-fd")) {
904 int fd;
905 if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
906 log_debug("Failed to parse job-timer-watch-fd value %s", v);
907 else {
908 if (j->timer_watch.type == WATCH_JOB_TIMER)
909 close_nointr_nofail(j->timer_watch.fd);
910
911 j->timer_watch.type = WATCH_JOB_TIMER;
912 j->timer_watch.fd = fdset_remove(fds, fd);
913 j->timer_watch.data.job = j;
914 }
915 }
916 }
917 }
918
919 int job_coldplug(Job *j) {
920 struct epoll_event ev;
921
922 if (j->timer_watch.type != WATCH_JOB_TIMER)
923 return 0;
924
925 zero(ev);
926 ev.data.ptr = &j->timer_watch;
927 ev.events = EPOLLIN;
928
929 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
930 return -errno;
931
932 return 0;
933 }
934
935 static const char* const job_state_table[_JOB_STATE_MAX] = {
936 [JOB_WAITING] = "waiting",
937 [JOB_RUNNING] = "running"
938 };
939
940 DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
941
942 static const char* const job_type_table[_JOB_TYPE_MAX] = {
943 [JOB_START] = "start",
944 [JOB_VERIFY_ACTIVE] = "verify-active",
945 [JOB_STOP] = "stop",
946 [JOB_RELOAD] = "reload",
947 [JOB_RELOAD_OR_START] = "reload-or-start",
948 [JOB_RESTART] = "restart",
949 [JOB_TRY_RESTART] = "try-restart",
950 [JOB_NOP] = "nop",
951 };
952
953 DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
954
955 static const char* const job_mode_table[_JOB_MODE_MAX] = {
956 [JOB_FAIL] = "fail",
957 [JOB_REPLACE] = "replace",
958 [JOB_ISOLATE] = "isolate",
959 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
960 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
961 };
962
963 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
964
965 static const char* const job_result_table[_JOB_RESULT_MAX] = {
966 [JOB_DONE] = "done",
967 [JOB_CANCELED] = "canceled",
968 [JOB_TIMEOUT] = "timeout",
969 [JOB_FAILED] = "failed",
970 [JOB_DEPENDENCY] = "dependency",
971 [JOB_SKIPPED] = "skipped"
972 };
973
974 DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);