chiark / gitweb /
bfb6b7443a8673a52b25b9c4006ffdc6536548a9
[elogind.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 Job* job_new(Unit *unit, JobType type) {
37         Job *j;
38
39         assert(type < _JOB_TYPE_MAX);
40         assert(unit);
41
42         if (!(j = new0(Job, 1)))
43                 return NULL;
44
45         j->manager = unit->manager;
46         j->id = j->manager->current_job_id++;
47         j->type = type;
48         j->unit = unit;
49
50         j->timer_watch.type = WATCH_INVALID;
51
52         /* We don't link it here, that's what job_dependency() is for */
53
54         return j;
55 }
56
57 void job_uninstall(Job *j) {
58         assert(j->installed);
59         /* Detach from next 'bigger' objects */
60
61         bus_job_send_removed_signal(j);
62
63         if (j->unit->job == j) {
64                 j->unit->job = NULL;
65                 unit_add_to_gc_queue(j->unit);
66         }
67
68         hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
69         j->installed = false;
70 }
71
72 void job_free(Job *j) {
73         assert(j);
74         assert(!j->installed);
75         assert(!j->transaction_prev);
76         assert(!j->transaction_next);
77         assert(!j->subject_list);
78         assert(!j->object_list);
79
80         if (j->in_run_queue)
81                 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
82
83         if (j->in_dbus_queue)
84                 LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
85
86         if (j->timer_watch.type != WATCH_INVALID) {
87                 assert(j->timer_watch.type == WATCH_JOB_TIMER);
88                 assert(j->timer_watch.data.job == j);
89                 assert(j->timer_watch.fd >= 0);
90
91                 assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
92                 close_nointr_nofail(j->timer_watch.fd);
93         }
94
95         free(j->bus_client);
96         free(j);
97 }
98
99 JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts, Transaction *tr) {
100         JobDependency *l;
101
102         assert(object);
103
104         /* Adds a new job link, which encodes that the 'subject' job
105          * needs the 'object' job in some way. If 'subject' is NULL
106          * this means the 'anchor' job (i.e. the one the user
107          * explicitly asked for) is the requester. */
108
109         if (!(l = new0(JobDependency, 1)))
110                 return NULL;
111
112         l->subject = subject;
113         l->object = object;
114         l->matters = matters;
115         l->conflicts = conflicts;
116
117         if (subject)
118                 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
119         else
120                 LIST_PREPEND(JobDependency, subject, tr->anchor, l);
121
122         LIST_PREPEND(JobDependency, object, object->object_list, l);
123
124         return l;
125 }
126
127 void job_dependency_free(JobDependency *l, Transaction *tr) {
128         assert(l);
129
130         if (l->subject)
131                 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
132         else
133                 LIST_REMOVE(JobDependency, subject, tr->anchor, l);
134
135         LIST_REMOVE(JobDependency, object, l->object->object_list, l);
136
137         free(l);
138 }
139
140 void job_dump(Job *j, FILE*f, const char *prefix) {
141         assert(j);
142         assert(f);
143
144         if (!prefix)
145                 prefix = "";
146
147         fprintf(f,
148                 "%s-> Job %u:\n"
149                 "%s\tAction: %s -> %s\n"
150                 "%s\tState: %s\n"
151                 "%s\tForced: %s\n",
152                 prefix, j->id,
153                 prefix, j->unit->id, job_type_to_string(j->type),
154                 prefix, job_state_to_string(j->state),
155                 prefix, yes_no(j->override));
156 }
157
158 bool job_is_anchor(Job *j) {
159         JobDependency *l;
160
161         assert(j);
162
163         LIST_FOREACH(object, l, j->object_list)
164                 if (!l->subject)
165                         return true;
166
167         return false;
168 }
169
170 /*
171  * Merging is commutative, so imagine the matrix as symmetric. We store only
172  * its lower triangle to avoid duplication. We don't store the main diagonal,
173  * because A merged with A is simply A.
174  *
175  * Merging is associative! A merged with B merged with C is the same as
176  * A merged with C merged with B.
177  *
178  * Mergeability is transitive! If A can be merged with B and B with C then
179  * A also with C.
180  *
181  * Also, if A merged with B cannot be merged with C, then either A or B cannot
182  * be merged with C either.
183  */
184 static const JobType job_merging_table[] = {
185 /* What \ With       *  JOB_START         JOB_VERIFY_ACTIVE  JOB_STOP JOB_RELOAD   JOB_RELOAD_OR_START  JOB_RESTART JOB_TRY_RESTART */
186 /************************************************************************************************************************************/
187 /*JOB_START          */
188 /*JOB_VERIFY_ACTIVE  */ JOB_START,
189 /*JOB_STOP           */ -1,                  -1,
190 /*JOB_RELOAD         */ JOB_RELOAD_OR_START, JOB_RELOAD,          -1,
191 /*JOB_RELOAD_OR_START*/ JOB_RELOAD_OR_START, JOB_RELOAD_OR_START, -1, JOB_RELOAD_OR_START,
192 /*JOB_RESTART        */ JOB_RESTART,         JOB_RESTART,         -1, JOB_RESTART,         JOB_RESTART,
193 /*JOB_TRY_RESTART    */ JOB_RESTART,         JOB_TRY_RESTART,     -1, JOB_TRY_RESTART,     JOB_RESTART, JOB_RESTART,
194 };
195
196 JobType job_type_lookup_merge(JobType a, JobType b) {
197         assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX * (_JOB_TYPE_MAX - 1) / 2);
198         assert(a >= 0 && a < _JOB_TYPE_MAX);
199         assert(b >= 0 && b < _JOB_TYPE_MAX);
200
201         if (a == b)
202                 return a;
203
204         if (a < b) {
205                 JobType tmp = a;
206                 a = b;
207                 b = tmp;
208         }
209
210         return job_merging_table[(a - 1) * a / 2 + b];
211 }
212
213 bool job_type_is_redundant(JobType a, UnitActiveState b) {
214         switch (a) {
215
216         case JOB_START:
217                 return
218                         b == UNIT_ACTIVE ||
219                         b == UNIT_RELOADING;
220
221         case JOB_STOP:
222                 return
223                         b == UNIT_INACTIVE ||
224                         b == UNIT_FAILED;
225
226         case JOB_VERIFY_ACTIVE:
227                 return
228                         b == UNIT_ACTIVE ||
229                         b == UNIT_RELOADING;
230
231         case JOB_RELOAD:
232                 return
233                         b == UNIT_RELOADING;
234
235         case JOB_RELOAD_OR_START:
236                 return
237                         b == UNIT_ACTIVATING ||
238                         b == UNIT_RELOADING;
239
240         case JOB_RESTART:
241                 return
242                         b == UNIT_ACTIVATING;
243
244         case JOB_TRY_RESTART:
245                 return
246                         b == UNIT_ACTIVATING;
247
248         default:
249                 assert_not_reached("Invalid job type");
250         }
251 }
252
253 bool job_is_runnable(Job *j) {
254         Iterator i;
255         Unit *other;
256
257         assert(j);
258         assert(j->installed);
259
260         /* Checks whether there is any job running for the units this
261          * job needs to be running after (in the case of a 'positive'
262          * job type) or before (in the case of a 'negative' job
263          * type. */
264
265         /* First check if there is an override */
266         if (j->ignore_order)
267                 return true;
268
269         if (j->type == JOB_START ||
270             j->type == JOB_VERIFY_ACTIVE ||
271             j->type == JOB_RELOAD ||
272             j->type == JOB_RELOAD_OR_START) {
273
274                 /* Immediate result is that the job is or might be
275                  * started. In this case lets wait for the
276                  * dependencies, regardless whether they are
277                  * starting or stopping something. */
278
279                 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
280                         if (other->job)
281                                 return false;
282         }
283
284         /* Also, if something else is being stopped and we should
285          * change state after it, then lets wait. */
286
287         SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
288                 if (other->job &&
289                     (other->job->type == JOB_STOP ||
290                      other->job->type == JOB_RESTART ||
291                      other->job->type == JOB_TRY_RESTART))
292                         return false;
293
294         /* This means that for a service a and a service b where b
295          * shall be started after a:
296          *
297          *  start a + start b â†’ 1st step start a, 2nd step start b
298          *  start a + stop b  â†’ 1st step stop b,  2nd step start a
299          *  stop a  + start b â†’ 1st step stop a,  2nd step start b
300          *  stop a  + stop b  â†’ 1st step stop b,  2nd step stop a
301          *
302          *  This has the side effect that restarts are properly
303          *  synchronized too. */
304
305         return true;
306 }
307
308 static void job_change_type(Job *j, JobType newtype) {
309         log_debug("Converting job %s/%s -> %s/%s",
310                   j->unit->id, job_type_to_string(j->type),
311                   j->unit->id, job_type_to_string(newtype));
312
313         j->type = newtype;
314 }
315
316 int job_run_and_invalidate(Job *j) {
317         int r;
318         uint32_t id;
319         Manager *m;
320
321         assert(j);
322         assert(j->installed);
323
324         if (j->in_run_queue) {
325                 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
326                 j->in_run_queue = false;
327         }
328
329         if (j->state != JOB_WAITING)
330                 return 0;
331
332         if (!job_is_runnable(j))
333                 return -EAGAIN;
334
335         j->state = JOB_RUNNING;
336         job_add_to_dbus_queue(j);
337
338         /* While we execute this operation the job might go away (for
339          * example: because it is replaced by a new, conflicting
340          * job.) To make sure we don't access a freed job later on we
341          * store the id here, so that we can verify the job is still
342          * valid. */
343         id = j->id;
344         m = j->manager;
345
346         switch (j->type) {
347
348                 case JOB_RELOAD_OR_START:
349                         if (unit_active_state(j->unit) == UNIT_ACTIVE) {
350                                 job_change_type(j, JOB_RELOAD);
351                                 r = unit_reload(j->unit);
352                                 break;
353                         }
354                         job_change_type(j, JOB_START);
355                         /* fall through */
356
357                 case JOB_START:
358                         r = unit_start(j->unit);
359
360                         /* If this unit cannot be started, then simply wait */
361                         if (r == -EBADR)
362                                 r = 0;
363                         break;
364
365                 case JOB_VERIFY_ACTIVE: {
366                         UnitActiveState t = unit_active_state(j->unit);
367                         if (UNIT_IS_ACTIVE_OR_RELOADING(t))
368                                 r = -EALREADY;
369                         else if (t == UNIT_ACTIVATING)
370                                 r = -EAGAIN;
371                         else
372                                 r = -ENOEXEC;
373                         break;
374                 }
375
376                 case JOB_TRY_RESTART:
377                         if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(j->unit))) {
378                                 r = -ENOEXEC;
379                                 break;
380                         }
381                         job_change_type(j, JOB_RESTART);
382                         /* fall through */
383
384                 case JOB_STOP:
385                 case JOB_RESTART:
386                         r = unit_stop(j->unit);
387
388                         /* If this unit cannot stopped, then simply wait. */
389                         if (r == -EBADR)
390                                 r = 0;
391                         break;
392
393                 case JOB_RELOAD:
394                         r = unit_reload(j->unit);
395                         break;
396
397                 default:
398                         assert_not_reached("Unknown job type");
399         }
400
401         if ((j = manager_get_job(m, id))) {
402                 if (r == -EALREADY)
403                         r = job_finish_and_invalidate(j, JOB_DONE);
404                 else if (r == -ENOEXEC)
405                         r = job_finish_and_invalidate(j, JOB_SKIPPED);
406                 else if (r == -EAGAIN)
407                         j->state = JOB_WAITING;
408                 else if (r < 0)
409                         r = job_finish_and_invalidate(j, JOB_FAILED);
410         }
411
412         return r;
413 }
414
415 static void job_print_status_message(Unit *u, JobType t, JobResult result) {
416         assert(u);
417
418         if (t == JOB_START) {
419
420                 switch (result) {
421
422                 case JOB_DONE:
423                         if (u->condition_result)
424                                 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON "  OK  " ANSI_HIGHLIGHT_OFF, "Started %s", unit_description(u));
425                         break;
426
427                 case JOB_FAILED:
428                         unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, "Failed to start %s", unit_description(u));
429                         unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
430                         break;
431
432                 case JOB_DEPENDENCY:
433                         unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " ABORT" ANSI_HIGHLIGHT_OFF, "Dependency failed. Aborted start of %s", unit_description(u));
434                         break;
435
436                 case JOB_TIMEOUT:
437                         unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out starting %s", unit_description(u));
438                         break;
439
440                 default:
441                         ;
442                 }
443
444         } else if (t == JOB_STOP) {
445
446                 switch (result) {
447
448                 case JOB_TIMEOUT:
449                         unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out stopping %s", unit_description(u));
450                         break;
451
452                 case JOB_DONE:
453                 case JOB_FAILED:
454                         unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON "  OK  " ANSI_HIGHLIGHT_OFF, "Stopped %s", unit_description(u));
455                         break;
456
457                 default:
458                         ;
459                 }
460         }
461 }
462
463 int job_finish_and_invalidate(Job *j, JobResult result) {
464         Unit *u;
465         Unit *other;
466         JobType t;
467         Iterator i;
468         bool recursed = false;
469
470         assert(j);
471         assert(j->installed);
472
473         job_add_to_dbus_queue(j);
474
475         /* Patch restart jobs so that they become normal start jobs */
476         if (result == JOB_DONE && j->type == JOB_RESTART) {
477
478                 job_change_type(j, JOB_START);
479                 j->state = JOB_WAITING;
480
481                 job_add_to_run_queue(j);
482
483                 u = j->unit;
484                 goto finish;
485         }
486
487         j->result = result;
488
489         log_debug("Job %s/%s finished, result=%s", j->unit->id, job_type_to_string(j->type), job_result_to_string(result));
490
491         if (result == JOB_FAILED)
492                 j->manager->n_failed_jobs ++;
493
494         u = j->unit;
495         t = j->type;
496         job_uninstall(j);
497         job_free(j);
498
499         job_print_status_message(u, t, result);
500
501         /* Fail depending jobs on failure */
502         if (result != JOB_DONE) {
503
504                 if (t == JOB_START ||
505                     t == JOB_VERIFY_ACTIVE ||
506                     t == JOB_RELOAD_OR_START) {
507
508                         SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
509                                 if (other->job &&
510                                     (other->job->type == JOB_START ||
511                                      other->job->type == JOB_VERIFY_ACTIVE ||
512                                      other->job->type == JOB_RELOAD_OR_START)) {
513                                         job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
514                                         recursed = true;
515                                 }
516
517                         SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
518                                 if (other->job &&
519                                     (other->job->type == JOB_START ||
520                                      other->job->type == JOB_VERIFY_ACTIVE ||
521                                      other->job->type == JOB_RELOAD_OR_START)) {
522                                         job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
523                                         recursed = true;
524                                 }
525
526                         SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
527                                 if (other->job &&
528                                     !other->job->override &&
529                                     (other->job->type == JOB_START ||
530                                      other->job->type == JOB_VERIFY_ACTIVE ||
531                                      other->job->type == JOB_RELOAD_OR_START)) {
532                                         job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
533                                         recursed = true;
534                                 }
535
536                 } else if (t == JOB_STOP) {
537
538                         SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
539                                 if (other->job &&
540                                     (other->job->type == JOB_START ||
541                                      other->job->type == JOB_VERIFY_ACTIVE ||
542                                      other->job->type == JOB_RELOAD_OR_START)) {
543                                         job_finish_and_invalidate(other->job, JOB_DEPENDENCY);
544                                         recursed = true;
545                                 }
546                 }
547         }
548
549         /* Trigger OnFailure dependencies that are not generated by
550          * the unit itself. We don't tread JOB_CANCELED as failure in
551          * this context. And JOB_FAILURE is already handled by the
552          * unit itself. */
553         if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
554                 log_notice("Job %s/%s failed with result '%s'.",
555                            u->id,
556                            job_type_to_string(t),
557                            job_result_to_string(result));
558
559                 unit_trigger_on_failure(u);
560         }
561
562 finish:
563         /* Try to start the next jobs that can be started */
564         SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
565                 if (other->job)
566                         job_add_to_run_queue(other->job);
567         SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
568                 if (other->job)
569                         job_add_to_run_queue(other->job);
570
571         manager_check_finished(u->manager);
572
573         return recursed;
574 }
575
576 int job_start_timer(Job *j) {
577         struct itimerspec its;
578         struct epoll_event ev;
579         int fd, r;
580         assert(j);
581
582         if (j->unit->job_timeout <= 0 ||
583             j->timer_watch.type == WATCH_JOB_TIMER)
584                 return 0;
585
586         assert(j->timer_watch.type == WATCH_INVALID);
587
588         if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
589                 r = -errno;
590                 goto fail;
591         }
592
593         zero(its);
594         timespec_store(&its.it_value, j->unit->job_timeout);
595
596         if (timerfd_settime(fd, 0, &its, NULL) < 0) {
597                 r = -errno;
598                 goto fail;
599         }
600
601         zero(ev);
602         ev.data.ptr = &j->timer_watch;
603         ev.events = EPOLLIN;
604
605         if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
606                 r = -errno;
607                 goto fail;
608         }
609
610         j->timer_watch.type = WATCH_JOB_TIMER;
611         j->timer_watch.fd = fd;
612         j->timer_watch.data.job = j;
613
614         return 0;
615
616 fail:
617         if (fd >= 0)
618                 close_nointr_nofail(fd);
619
620         return r;
621 }
622
623 void job_add_to_run_queue(Job *j) {
624         assert(j);
625         assert(j->installed);
626
627         if (j->in_run_queue)
628                 return;
629
630         LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
631         j->in_run_queue = true;
632 }
633
634 void job_add_to_dbus_queue(Job *j) {
635         assert(j);
636         assert(j->installed);
637
638         if (j->in_dbus_queue)
639                 return;
640
641         /* We don't check if anybody is subscribed here, since this
642          * job might just have been created and not yet assigned to a
643          * connection/client. */
644
645         LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
646         j->in_dbus_queue = true;
647 }
648
649 char *job_dbus_path(Job *j) {
650         char *p;
651
652         assert(j);
653
654         if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
655                 return NULL;
656
657         return p;
658 }
659
660 void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
661         assert(j);
662         assert(w == &j->timer_watch);
663
664         log_warning("Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
665         job_finish_and_invalidate(j, JOB_TIMEOUT);
666 }
667
668 static const char* const job_state_table[_JOB_STATE_MAX] = {
669         [JOB_WAITING] = "waiting",
670         [JOB_RUNNING] = "running"
671 };
672
673 DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
674
675 static const char* const job_type_table[_JOB_TYPE_MAX] = {
676         [JOB_START] = "start",
677         [JOB_VERIFY_ACTIVE] = "verify-active",
678         [JOB_STOP] = "stop",
679         [JOB_RELOAD] = "reload",
680         [JOB_RELOAD_OR_START] = "reload-or-start",
681         [JOB_RESTART] = "restart",
682         [JOB_TRY_RESTART] = "try-restart",
683 };
684
685 DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
686
687 static const char* const job_mode_table[_JOB_MODE_MAX] = {
688         [JOB_FAIL] = "fail",
689         [JOB_REPLACE] = "replace",
690         [JOB_ISOLATE] = "isolate",
691         [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
692         [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
693 };
694
695 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
696
697 static const char* const job_result_table[_JOB_RESULT_MAX] = {
698         [JOB_DONE] = "done",
699         [JOB_CANCELED] = "canceled",
700         [JOB_TIMEOUT] = "timeout",
701         [JOB_FAILED] = "failed",
702         [JOB_DEPENDENCY] = "dependency",
703         [JOB_SKIPPED] = "skipped"
704 };
705
706 DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);