chiark / gitweb /
util: generalize code that checks whether PIDs are alive or unwaited for
[elogind.git] / src / core / busname.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 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 "special.h"
23 #include "bus-kernel.h"
24 #include "bus-internal.h"
25 #include "bus-util.h"
26 #include "service.h"
27 #include "dbus-busname.h"
28 #include "busname.h"
29
30 static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
31         [BUSNAME_DEAD] = UNIT_INACTIVE,
32         [BUSNAME_LISTENING] = UNIT_ACTIVE,
33         [BUSNAME_RUNNING] = UNIT_ACTIVE,
34         [BUSNAME_FAILED] = UNIT_FAILED
35 };
36
37 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
38
39 static void busname_init(Unit *u) {
40         BusName *n = BUSNAME(u);
41
42         assert(u);
43         assert(u->load_state == UNIT_STUB);
44
45         n->starter_fd = -1;
46 }
47
48 static void busname_done(Unit *u) {
49         BusName *n = BUSNAME(u);
50
51         assert(u);
52
53         free(n->name);
54         n->name = NULL;
55
56         unit_ref_unset(&n->service);
57
58         n->event_source = sd_event_source_unref(n->event_source);
59
60         if (n->starter_fd >= 0) {
61                 close_nointr_nofail(n->starter_fd);
62                 n->starter_fd = -1;
63         }
64 }
65
66 static int busname_add_default_default_dependencies(BusName *n) {
67         int r;
68
69         assert(n);
70
71         r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
72         if (r < 0)
73                 return r;
74
75         if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
76                 r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
77                 if (r < 0)
78                         return r;
79         }
80
81         return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
82 }
83
84 static int busname_add_extras(BusName *n) {
85         Unit *u = UNIT(n);
86         int r;
87
88         assert(n);
89
90         if (!n->name) {
91                 n->name = unit_name_to_prefix(u->id);
92                 if (!n->name)
93                         return -ENOMEM;
94         }
95
96         if (!u->description) {
97                 r = unit_set_description(u, n->name);
98                 if (r < 0)
99                         return r;
100         }
101
102         if (!UNIT_DEREF(n->service)) {
103                 Unit *x;
104
105                 r = unit_load_related_unit(u, ".service", &x);
106                 if (r < 0)
107                         return r;
108
109                 unit_ref_set(&n->service, x);
110         }
111
112         r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
113         if (r < 0)
114                 return r;
115
116         if (u->default_dependencies) {
117                 r = busname_add_default_default_dependencies(n);
118                 if (r < 0)
119                         return r;
120         }
121
122         return 0;
123 }
124
125
126
127 static int busname_verify(BusName *n) {
128         char *e;
129
130         assert(n);
131
132         if (UNIT(n)->load_state != UNIT_LOADED)
133                 return 0;
134
135         if (!service_name_is_valid(n->name)) {
136                 log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
137                 return -EINVAL;
138         }
139
140         e = strappenda(n->name, ".busname");
141         if (!unit_has_name(UNIT(n), e)) {
142                 log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
143                 return -EINVAL;
144         }
145
146         return 0;
147 }
148
149 static int busname_load(Unit *u) {
150         BusName *n = BUSNAME(u);
151         int r;
152
153         assert(u);
154         assert(u->load_state == UNIT_STUB);
155
156         r = unit_load_fragment_and_dropin(u);
157         if (r < 0)
158                 return r;
159
160         if (u->load_state == UNIT_LOADED) {
161                 /* This is a new unit? Then let's add in some extras */
162                 r = busname_add_extras(n);
163                 if (r < 0)
164                         return r;
165         }
166
167         return busname_verify(n);
168 }
169
170 static void busname_dump(Unit *u, FILE *f, const char *prefix) {
171         BusName *n = BUSNAME(u);
172
173         assert(n);
174         assert(f);
175
176         fprintf(f,
177                 "%sBus Name State: %s\n"
178                 "%sResult: %s\n"
179                 "%sName: %s\n",
180                 prefix, busname_state_to_string(n->state),
181                 prefix, busname_result_to_string(n->result),
182                 prefix, n->name);
183 }
184
185 static void busname_unwatch_fd(BusName *n) {
186         int r;
187
188         assert(n);
189
190         if (n->event_source) {
191                 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
192                 if (r < 0)
193                         log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
194         }
195 }
196
197 static void busname_close_fd(BusName *n) {
198         assert(n);
199
200         busname_unwatch_fd(n);
201
202         if (n->starter_fd <= 0)
203                 return;
204
205         close_nointr_nofail(n->starter_fd);
206         n->starter_fd = -1;
207 }
208
209 static int busname_watch_fd(BusName *n) {
210         int r;
211
212         assert(n);
213
214         if (n->starter_fd < 0)
215                 return 0;
216
217         if (n->event_source)
218                 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
219         else
220                 r = sd_event_add_io(UNIT(n)->manager->event, n->starter_fd, EPOLLIN, busname_dispatch_io, n, &n->event_source);
221         if (r < 0) {
222                 log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
223                 busname_unwatch_fd(n);
224                 return r;
225         }
226
227         return 0;
228 }
229
230 static int busname_open_fd(BusName *n) {
231         assert(n);
232
233         if (n->starter_fd >= 0)
234                 return 0;
235
236         n->starter_fd = bus_kernel_create_starter(UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user", n->name);
237         if (n->starter_fd < 0) {
238                 log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
239                 return n->starter_fd;
240         }
241
242         return 0;
243 }
244
245 static void busname_set_state(BusName *n, BusNameState state) {
246         BusNameState old_state;
247         assert(n);
248
249         old_state = n->state;
250         n->state = state;
251
252         if (state != BUSNAME_LISTENING)
253                 busname_unwatch_fd(n);
254
255         if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_RUNNING))
256                 busname_close_fd(n);
257
258         if (state != old_state)
259                 log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
260                                UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
261
262         unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
263 }
264
265 static int busname_coldplug(Unit *u) {
266         BusName *n = BUSNAME(u);
267         int r;
268
269         assert(n);
270         assert(n->state == BUSNAME_DEAD);
271
272         if (n->deserialized_state == n->state)
273                 return 0;
274
275         if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_RUNNING)) {
276                 r = busname_open_fd(n);
277                 if (r < 0)
278                         return r;
279         }
280
281         if (n->deserialized_state == BUSNAME_LISTENING) {
282                 r = busname_watch_fd(n);
283                 if (r < 0)
284                         return r;
285         }
286
287         busname_set_state(n, n->deserialized_state);
288         return 0;
289 }
290
291 static void busname_enter_dead(BusName *n, BusNameResult f) {
292         assert(n);
293
294         if (f != BUSNAME_SUCCESS)
295                 n->result = f;
296
297         busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
298 }
299
300 static void busname_enter_listening(BusName *n) {
301         int r;
302
303         assert(n);
304
305         r = busname_open_fd(n);
306         if (r < 0) {
307                 log_warning_unit(UNIT(n)->id, "%s failed to listen on bus names: %s", UNIT(n)->id, strerror(-r));
308                 goto fail;
309         }
310
311         r = busname_watch_fd(n);
312         if (r < 0) {
313                 log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
314                 goto fail;
315         }
316
317         busname_set_state(n, BUSNAME_LISTENING);
318         return;
319
320 fail:
321         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
322 }
323
324 static void busname_enter_running(BusName *n) {
325         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
326         bool pending = false;
327         Unit *other;
328         Iterator i;
329         int r;
330
331         assert(n);
332
333         /* We don't take conenctions anymore if we are supposed to
334          * shut down anyway */
335
336         if (unit_stop_pending(UNIT(n))) {
337                 log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
338
339                 /* Flush all queued activation reqeuest by closing and reopening the connection */
340                 bus_kernel_drop_one(n->starter_fd);
341
342                 busname_enter_listening(n);
343                 return;
344         }
345
346         /* If there's already a start pending don't bother to do
347          * anything */
348         SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
349                 if (unit_active_or_pending(other)) {
350                         pending = true;
351                         break;
352                 }
353
354         if (!pending) {
355                 r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
356                 if (r < 0)
357                         goto fail;
358         }
359
360         busname_set_state(n, BUSNAME_RUNNING);
361         return;
362
363 fail:
364         log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
365         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
366 }
367
368 static int busname_start(Unit *u) {
369         BusName *n = BUSNAME(u);
370
371         assert(n);
372
373         if (UNIT_ISSET(n->service)) {
374                 Service *service;
375
376                 service = SERVICE(UNIT_DEREF(n->service));
377
378                 if (UNIT(service)->load_state != UNIT_LOADED) {
379                         log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
380                         return -ENOENT;
381                 }
382         }
383
384         assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
385
386         n->result = BUSNAME_SUCCESS;
387         busname_enter_listening(n);
388
389         return 0;
390 }
391
392 static int busname_stop(Unit *u) {
393         BusName *n = BUSNAME(u);
394
395         assert(n);
396         assert(n->state == BUSNAME_LISTENING || n->state == BUSNAME_RUNNING);
397
398         busname_enter_dead(n, BUSNAME_SUCCESS);
399         return 0;
400 }
401
402 static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
403         BusName *n = BUSNAME(u);
404
405         assert(n);
406         assert(f);
407         assert(fds);
408
409         unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
410         unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
411
412         if (n->starter_fd >= 0) {
413                 int copy;
414
415                 copy = fdset_put_dup(fds, n->starter_fd);
416                 if (copy < 0)
417                         return copy;
418
419                 unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
420         }
421
422         return 0;
423 }
424
425 static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
426         BusName *n = BUSNAME(u);
427
428         assert(n);
429         assert(key);
430         assert(value);
431
432         if (streq(key, "state")) {
433                 BusNameState state;
434
435                 state = busname_state_from_string(value);
436                 if (state < 0)
437                         log_debug_unit(u->id, "Failed to parse state value %s", value);
438                 else
439                         n->deserialized_state = state;
440
441         } else if (streq(key, "result")) {
442                 BusNameResult f;
443
444                 f = busname_result_from_string(value);
445                 if (f < 0)
446                         log_debug_unit(u->id, "Failed to parse result value %s", value);
447                 else if (f != BUSNAME_SUCCESS)
448                         n->result = f;
449
450         } else if (streq(key, "starter-fd")) {
451                 int fd;
452
453                 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
454                         log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
455                 else {
456                         if (n->starter_fd >= 0)
457                                 close_nointr_nofail(n->starter_fd);
458                         n->starter_fd = fdset_remove(fds, fd);
459                 }
460         } else
461                 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
462
463         return 0;
464 }
465
466 _pure_ static UnitActiveState busname_active_state(Unit *u) {
467         assert(u);
468
469         return state_translation_table[BUSNAME(u)->state];
470 }
471
472 _pure_ static const char *busname_sub_state_to_string(Unit *u) {
473         assert(u);
474
475         return busname_state_to_string(BUSNAME(u)->state);
476 }
477
478 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
479         BusName *n = userdata;
480
481         assert(n);
482         assert(fd >= 0);
483
484         if (n->state != BUSNAME_LISTENING)
485                 return 0;
486
487         log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
488
489         if (revents != EPOLLIN) {
490                 log_error_unit(UNIT(n)->id, "%s: Got unexpected poll event (0x%x) on starter fd.",
491                                UNIT(n)->id, revents);
492                 goto fail;
493         }
494
495         busname_enter_running(n);
496         return 0;
497 fail:
498
499         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
500         return 0;
501 }
502
503 static void busname_reset_failed(Unit *u) {
504         BusName *n = BUSNAME(u);
505
506         assert(n);
507
508         if (n->state == BUSNAME_FAILED)
509                 busname_set_state(n, BUSNAME_DEAD);
510
511         n->result = BUSNAME_SUCCESS;
512 }
513
514 static void busname_trigger_notify(Unit *u, Unit *other) {
515         BusName *n = BUSNAME(u);
516         Service *s;
517
518         assert(n);
519         assert(other);
520
521         if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
522                 return;
523
524         if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
525                 return;
526
527         s = SERVICE(other);
528
529         if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
530                 busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
531         else if (IN_SET(s->state,
532                         SERVICE_DEAD, SERVICE_FAILED,
533                         SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
534                         SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
535                         SERVICE_AUTO_RESTART))
536                 busname_enter_listening(n);
537 }
538
539 static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
540         [BUSNAME_DEAD] = "dead",
541         [BUSNAME_LISTENING] = "listening",
542         [BUSNAME_RUNNING] = "running",
543         [BUSNAME_FAILED] = "failed"
544 };
545
546 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
547
548 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
549         [BUSNAME_SUCCESS] = "success",
550         [BUSNAME_FAILURE_RESOURCES] = "resources",
551 };
552
553 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
554
555 const UnitVTable busname_vtable = {
556         .object_size = sizeof(BusName),
557
558         .sections =
559                 "Unit\0"
560                 "BusName\0"
561                 "Install\0",
562         .private_section = "BusName",
563
564         .init = busname_init,
565         .done = busname_done,
566         .load = busname_load,
567
568         .coldplug = busname_coldplug,
569
570         .dump = busname_dump,
571
572         .start = busname_start,
573         .stop = busname_stop,
574
575         .serialize = busname_serialize,
576         .deserialize_item = busname_deserialize_item,
577
578         .active_state = busname_active_state,
579         .sub_state_to_string = busname_sub_state_to_string,
580
581         .trigger_notify = busname_trigger_notify,
582
583         .reset_failed = busname_reset_failed,
584
585         .bus_interface = "org.freedesktop.systemd1.BusName",
586         .bus_vtable = bus_busname_vtable,
587
588         .status_message_formats = {
589                 .finished_start_job = {
590                         [JOB_DONE]       = "Listening on %s.",
591                         [JOB_FAILED]     = "Failed to listen on %s.",
592                         [JOB_DEPENDENCY] = "Dependency failed for %s.",
593                         [JOB_TIMEOUT]    = "Timed out starting %s.",
594                 },
595                 .finished_stop_job = {
596                         [JOB_DONE]       = "Closed %s.",
597                         [JOB_FAILED]     = "Failed stopping %s.",
598                         [JOB_TIMEOUT]    = "Timed out stopping %s.",
599                 },
600         },
601 };