]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-event/sd-event.c
sd-event: make _ref() calls NOPs when NULL is passed to them
[thirdparty/systemd.git] / src / libsystemd / sd-event / sd-event.c
CommitLineData
fd38203a
LP
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 <sys/epoll.h>
23#include <sys/timerfd.h>
24#include <sys/wait.h>
25
cde93897 26#include "sd-daemon.h"
07630cea
LP
27#include "sd-event.h"
28#include "sd-id128.h"
29
b5efdb8a 30#include "alloc-util.h"
3ffd4af2 31#include "fd-util.h"
fd38203a 32#include "hashmap.h"
07630cea
LP
33#include "list.h"
34#include "macro.h"
afc6adb5 35#include "missing.h"
07630cea 36#include "prioq.h"
4a0b58c4 37#include "process-util.h"
6e9feda3 38#include "set.h"
24882e06 39#include "signal-util.h"
07630cea
LP
40#include "string-util.h"
41#include "time-util.h"
42#include "util.h"
fd38203a 43
c2ba3ad6 44#define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC)
fd38203a
LP
45
46typedef enum EventSourceType {
47 SOURCE_IO,
6a0f1f6d 48 SOURCE_TIME_REALTIME,
a8548816 49 SOURCE_TIME_BOOTTIME,
6a0f1f6d
LP
50 SOURCE_TIME_MONOTONIC,
51 SOURCE_TIME_REALTIME_ALARM,
52 SOURCE_TIME_BOOTTIME_ALARM,
fd38203a
LP
53 SOURCE_SIGNAL,
54 SOURCE_CHILD,
da7e457c 55 SOURCE_DEFER,
6e9feda3 56 SOURCE_POST,
6203e07a 57 SOURCE_EXIT,
6a0f1f6d 58 SOURCE_WATCHDOG,
a71fe8b8 59 _SOURCE_EVENT_SOURCE_TYPE_MAX,
6a0f1f6d 60 _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
fd38203a
LP
61} EventSourceType;
62
9da4cb2b
LP
63/* All objects we use in epoll events start with this value, so that
64 * we know how to dispatch it */
65typedef enum WakeupType {
66 WAKEUP_NONE,
67 WAKEUP_EVENT_SOURCE,
68 WAKEUP_CLOCK_DATA,
69 WAKEUP_SIGNAL_DATA,
70 _WAKEUP_TYPE_MAX,
71 _WAKEUP_TYPE_INVALID = -1,
72} WakeupType;
73
a8548816 74#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM)
6a0f1f6d 75
fd38203a 76struct sd_event_source {
9da4cb2b
LP
77 WakeupType wakeup;
78
da7e457c 79 unsigned n_ref;
fd38203a
LP
80
81 sd_event *event;
82 void *userdata;
718db961 83 sd_event_handler_t prepare;
fd38203a 84
356779df 85 char *description;
f7f53e9e 86
6a0f1f6d 87 EventSourceType type:5;
baf76283 88 int enabled:3;
fd38203a 89 bool pending:1;
12179984 90 bool dispatching:1;
a71fe8b8 91 bool floating:1;
fd38203a 92
31927c16 93 int64_t priority;
fd38203a
LP
94 unsigned pending_index;
95 unsigned prepare_index;
96 unsigned pending_iteration;
97 unsigned prepare_iteration;
98
a71fe8b8
LP
99 LIST_FIELDS(sd_event_source, sources);
100
fd38203a
LP
101 union {
102 struct {
718db961 103 sd_event_io_handler_t callback;
fd38203a
LP
104 int fd;
105 uint32_t events;
106 uint32_t revents;
107 bool registered:1;
108 } io;
109 struct {
718db961 110 sd_event_time_handler_t callback;
c2ba3ad6
LP
111 usec_t next, accuracy;
112 unsigned earliest_index;
113 unsigned latest_index;
fd38203a
LP
114 } time;
115 struct {
718db961 116 sd_event_signal_handler_t callback;
fd38203a
LP
117 struct signalfd_siginfo siginfo;
118 int sig;
119 } signal;
120 struct {
718db961 121 sd_event_child_handler_t callback;
fd38203a
LP
122 siginfo_t siginfo;
123 pid_t pid;
124 int options;
125 } child;
126 struct {
718db961 127 sd_event_handler_t callback;
fd38203a 128 } defer;
6e9feda3
LP
129 struct {
130 sd_event_handler_t callback;
131 } post;
da7e457c 132 struct {
718db961 133 sd_event_handler_t callback;
da7e457c 134 unsigned prioq_index;
6203e07a 135 } exit;
fd38203a
LP
136 };
137};
138
6a0f1f6d 139struct clock_data {
9da4cb2b 140 WakeupType wakeup;
6a0f1f6d
LP
141 int fd;
142
143 /* For all clocks we maintain two priority queues each, one
144 * ordered for the earliest times the events may be
145 * dispatched, and one ordered by the latest times they must
146 * have been dispatched. The range between the top entries in
147 * the two prioqs is the time window we can freely schedule
148 * wakeups in */
149
150 Prioq *earliest;
151 Prioq *latest;
152 usec_t next;
212bbb17
TG
153
154 bool needs_rearm:1;
6a0f1f6d
LP
155};
156
9da4cb2b
LP
157struct signal_data {
158 WakeupType wakeup;
159
160 /* For each priority we maintain one signal fd, so that we
161 * only have to dequeue a single event per priority at a
162 * time. */
163
164 int fd;
165 int64_t priority;
166 sigset_t sigset;
167 sd_event_source *current;
168};
169
fd38203a 170struct sd_event {
da7e457c 171 unsigned n_ref;
fd38203a
LP
172
173 int epoll_fd;
cde93897 174 int watchdog_fd;
fd38203a
LP
175
176 Prioq *pending;
177 Prioq *prepare;
c2ba3ad6 178
a8548816 179 /* timerfd_create() only supports these five clocks so far. We
6a0f1f6d
LP
180 * can add support for more clocks when the kernel learns to
181 * deal with them, too. */
182 struct clock_data realtime;
a8548816 183 struct clock_data boottime;
6a0f1f6d
LP
184 struct clock_data monotonic;
185 struct clock_data realtime_alarm;
186 struct clock_data boottime_alarm;
fd38203a 187
da7e457c
LP
188 usec_t perturb;
189
9da4cb2b
LP
190 sd_event_source **signal_sources; /* indexed by signal number */
191 Hashmap *signal_data; /* indexed by priority */
fd38203a
LP
192
193 Hashmap *child_sources;
baf76283 194 unsigned n_enabled_child_sources;
fd38203a 195
6e9feda3
LP
196 Set *post_sources;
197
6203e07a 198 Prioq *exit;
fd38203a 199
da7e457c 200 pid_t original_pid;
c2ba3ad6 201
da7e457c 202 unsigned iteration;
46e8c825 203 dual_timestamp timestamp;
6a0f1f6d 204 usec_t timestamp_boottime;
da7e457c 205 int state;
eaa3cbef 206
6203e07a 207 bool exit_requested:1;
da7e457c 208 bool need_process_child:1;
cde93897 209 bool watchdog:1;
afc6adb5 210
6203e07a
LP
211 int exit_code;
212
afc6adb5
LP
213 pid_t tid;
214 sd_event **default_event_ptr;
cde93897
LP
215
216 usec_t watchdog_last, watchdog_period;
15b38f93
LP
217
218 unsigned n_sources;
a71fe8b8
LP
219
220 LIST_HEAD(sd_event_source, sources);
fd38203a
LP
221};
222
a71fe8b8
LP
223static void source_disconnect(sd_event_source *s);
224
fd38203a
LP
225static int pending_prioq_compare(const void *a, const void *b) {
226 const sd_event_source *x = a, *y = b;
227
228 assert(x->pending);
229 assert(y->pending);
230
baf76283
LP
231 /* Enabled ones first */
232 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 233 return -1;
baf76283 234 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
235 return 1;
236
237 /* Lower priority values first */
238 if (x->priority < y->priority)
239 return -1;
240 if (x->priority > y->priority)
241 return 1;
242
243 /* Older entries first */
244 if (x->pending_iteration < y->pending_iteration)
245 return -1;
246 if (x->pending_iteration > y->pending_iteration)
247 return 1;
248
fd38203a
LP
249 return 0;
250}
251
252static int prepare_prioq_compare(const void *a, const void *b) {
253 const sd_event_source *x = a, *y = b;
254
255 assert(x->prepare);
256 assert(y->prepare);
257
8046c457
KK
258 /* Enabled ones first */
259 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
260 return -1;
261 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
262 return 1;
263
fd38203a
LP
264 /* Move most recently prepared ones last, so that we can stop
265 * preparing as soon as we hit one that has already been
266 * prepared in the current iteration */
267 if (x->prepare_iteration < y->prepare_iteration)
268 return -1;
269 if (x->prepare_iteration > y->prepare_iteration)
270 return 1;
271
fd38203a
LP
272 /* Lower priority values first */
273 if (x->priority < y->priority)
274 return -1;
275 if (x->priority > y->priority)
276 return 1;
277
fd38203a
LP
278 return 0;
279}
280
c2ba3ad6 281static int earliest_time_prioq_compare(const void *a, const void *b) {
fd38203a
LP
282 const sd_event_source *x = a, *y = b;
283
6a0f1f6d
LP
284 assert(EVENT_SOURCE_IS_TIME(x->type));
285 assert(x->type == y->type);
fd38203a 286
baf76283
LP
287 /* Enabled ones first */
288 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 289 return -1;
baf76283 290 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
291 return 1;
292
293 /* Move the pending ones to the end */
294 if (!x->pending && y->pending)
295 return -1;
296 if (x->pending && !y->pending)
297 return 1;
298
299 /* Order by time */
300 if (x->time.next < y->time.next)
301 return -1;
302 if (x->time.next > y->time.next)
a99badf5 303 return 1;
fd38203a 304
fd38203a
LP
305 return 0;
306}
307
c2ba3ad6
LP
308static int latest_time_prioq_compare(const void *a, const void *b) {
309 const sd_event_source *x = a, *y = b;
310
6a0f1f6d
LP
311 assert(EVENT_SOURCE_IS_TIME(x->type));
312 assert(x->type == y->type);
c2ba3ad6 313
baf76283
LP
314 /* Enabled ones first */
315 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
c2ba3ad6 316 return -1;
baf76283 317 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
c2ba3ad6
LP
318 return 1;
319
320 /* Move the pending ones to the end */
321 if (!x->pending && y->pending)
322 return -1;
323 if (x->pending && !y->pending)
324 return 1;
325
326 /* Order by time */
327 if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
328 return -1;
329 if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
a99badf5 330 return 1;
c2ba3ad6 331
c2ba3ad6
LP
332 return 0;
333}
334
6203e07a 335static int exit_prioq_compare(const void *a, const void *b) {
da7e457c
LP
336 const sd_event_source *x = a, *y = b;
337
6203e07a
LP
338 assert(x->type == SOURCE_EXIT);
339 assert(y->type == SOURCE_EXIT);
da7e457c 340
baf76283
LP
341 /* Enabled ones first */
342 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
da7e457c 343 return -1;
baf76283 344 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
da7e457c
LP
345 return 1;
346
347 /* Lower priority values first */
348 if (x->priority < y->priority)
349 return -1;
350 if (x->priority > y->priority)
351 return 1;
352
da7e457c
LP
353 return 0;
354}
355
6a0f1f6d
LP
356static void free_clock_data(struct clock_data *d) {
357 assert(d);
9da4cb2b 358 assert(d->wakeup == WAKEUP_CLOCK_DATA);
6a0f1f6d
LP
359
360 safe_close(d->fd);
361 prioq_free(d->earliest);
362 prioq_free(d->latest);
363}
364
fd38203a 365static void event_free(sd_event *e) {
a71fe8b8
LP
366 sd_event_source *s;
367
fd38203a 368 assert(e);
a71fe8b8
LP
369
370 while ((s = e->sources)) {
371 assert(s->floating);
372 source_disconnect(s);
373 sd_event_source_unref(s);
374 }
375
15b38f93 376 assert(e->n_sources == 0);
fd38203a 377
afc6adb5
LP
378 if (e->default_event_ptr)
379 *(e->default_event_ptr) = NULL;
380
03e334a1 381 safe_close(e->epoll_fd);
03e334a1 382 safe_close(e->watchdog_fd);
cde93897 383
6a0f1f6d 384 free_clock_data(&e->realtime);
a8548816 385 free_clock_data(&e->boottime);
6a0f1f6d
LP
386 free_clock_data(&e->monotonic);
387 free_clock_data(&e->realtime_alarm);
388 free_clock_data(&e->boottime_alarm);
389
fd38203a
LP
390 prioq_free(e->pending);
391 prioq_free(e->prepare);
6203e07a 392 prioq_free(e->exit);
fd38203a
LP
393
394 free(e->signal_sources);
9da4cb2b 395 hashmap_free(e->signal_data);
fd38203a
LP
396
397 hashmap_free(e->child_sources);
6e9feda3 398 set_free(e->post_sources);
fd38203a
LP
399 free(e);
400}
401
f7262a9f 402_public_ int sd_event_new(sd_event** ret) {
fd38203a
LP
403 sd_event *e;
404 int r;
405
305f78bf 406 assert_return(ret, -EINVAL);
fd38203a
LP
407
408 e = new0(sd_event, 1);
409 if (!e)
410 return -ENOMEM;
411
da7e457c 412 e->n_ref = 1;
9da4cb2b 413 e->watchdog_fd = e->epoll_fd = e->realtime.fd = e->boottime.fd = e->monotonic.fd = e->realtime_alarm.fd = e->boottime_alarm.fd = -1;
3a43da28 414 e->realtime.next = e->boottime.next = e->monotonic.next = e->realtime_alarm.next = e->boottime_alarm.next = USEC_INFINITY;
9da4cb2b 415 e->realtime.wakeup = e->boottime.wakeup = e->monotonic.wakeup = e->realtime_alarm.wakeup = e->boottime_alarm.wakeup = WAKEUP_CLOCK_DATA;
eaa3cbef 416 e->original_pid = getpid();
3a43da28 417 e->perturb = USEC_INFINITY;
fd38203a 418
fd38203a
LP
419 e->pending = prioq_new(pending_prioq_compare);
420 if (!e->pending) {
421 r = -ENOMEM;
422 goto fail;
423 }
424
425 e->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
426 if (e->epoll_fd < 0) {
427 r = -errno;
428 goto fail;
429 }
430
431 *ret = e;
432 return 0;
433
434fail:
435 event_free(e);
436 return r;
437}
438
f7262a9f 439_public_ sd_event* sd_event_ref(sd_event *e) {
6680dd6b
LP
440
441 if (!e)
442 return NULL;
fd38203a 443
da7e457c
LP
444 assert(e->n_ref >= 1);
445 e->n_ref++;
fd38203a
LP
446
447 return e;
448}
449
f7262a9f 450_public_ sd_event* sd_event_unref(sd_event *e) {
5b1bc83f
LP
451
452 if (!e)
453 return NULL;
fd38203a 454
da7e457c
LP
455 assert(e->n_ref >= 1);
456 e->n_ref--;
457
458 if (e->n_ref <= 0)
fd38203a
LP
459 event_free(e);
460
461 return NULL;
462}
463
eaa3cbef
LP
464static bool event_pid_changed(sd_event *e) {
465 assert(e);
466
a2360a46 467 /* We don't support people creating an event loop and keeping
eaa3cbef
LP
468 * it around over a fork(). Let's complain. */
469
470 return e->original_pid != getpid();
471}
472
366e6411 473static void source_io_unregister(sd_event_source *s) {
fd38203a
LP
474 int r;
475
476 assert(s);
477 assert(s->type == SOURCE_IO);
478
f6806734 479 if (event_pid_changed(s->event))
366e6411 480 return;
f6806734 481
fd38203a 482 if (!s->io.registered)
366e6411 483 return;
fd38203a
LP
484
485 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL);
556c25cf
LP
486 if (r < 0)
487 log_debug_errno(errno, "Failed to remove source %s from epoll: %m", strna(s->description));
fd38203a
LP
488
489 s->io.registered = false;
fd38203a
LP
490}
491
305f78bf
LP
492static int source_io_register(
493 sd_event_source *s,
494 int enabled,
495 uint32_t events) {
496
fd38203a
LP
497 struct epoll_event ev = {};
498 int r;
499
500 assert(s);
501 assert(s->type == SOURCE_IO);
baf76283 502 assert(enabled != SD_EVENT_OFF);
fd38203a
LP
503
504 ev.events = events;
505 ev.data.ptr = s;
506
baf76283 507 if (enabled == SD_EVENT_ONESHOT)
fd38203a
LP
508 ev.events |= EPOLLONESHOT;
509
510 if (s->io.registered)
511 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev);
512 else
513 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_ADD, s->io.fd, &ev);
fd38203a
LP
514 if (r < 0)
515 return -errno;
516
517 s->io.registered = true;
518
519 return 0;
520}
521
6a0f1f6d
LP
522static clockid_t event_source_type_to_clock(EventSourceType t) {
523
524 switch (t) {
525
526 case SOURCE_TIME_REALTIME:
527 return CLOCK_REALTIME;
528
a8548816
TG
529 case SOURCE_TIME_BOOTTIME:
530 return CLOCK_BOOTTIME;
531
6a0f1f6d
LP
532 case SOURCE_TIME_MONOTONIC:
533 return CLOCK_MONOTONIC;
534
535 case SOURCE_TIME_REALTIME_ALARM:
536 return CLOCK_REALTIME_ALARM;
537
538 case SOURCE_TIME_BOOTTIME_ALARM:
539 return CLOCK_BOOTTIME_ALARM;
540
541 default:
542 return (clockid_t) -1;
543 }
544}
545
546static EventSourceType clock_to_event_source_type(clockid_t clock) {
547
548 switch (clock) {
549
550 case CLOCK_REALTIME:
551 return SOURCE_TIME_REALTIME;
552
a8548816
TG
553 case CLOCK_BOOTTIME:
554 return SOURCE_TIME_BOOTTIME;
555
6a0f1f6d
LP
556 case CLOCK_MONOTONIC:
557 return SOURCE_TIME_MONOTONIC;
558
559 case CLOCK_REALTIME_ALARM:
560 return SOURCE_TIME_REALTIME_ALARM;
561
562 case CLOCK_BOOTTIME_ALARM:
563 return SOURCE_TIME_BOOTTIME_ALARM;
564
565 default:
566 return _SOURCE_EVENT_SOURCE_TYPE_INVALID;
567 }
568}
569
570static struct clock_data* event_get_clock_data(sd_event *e, EventSourceType t) {
571 assert(e);
572
573 switch (t) {
574
575 case SOURCE_TIME_REALTIME:
576 return &e->realtime;
577
a8548816
TG
578 case SOURCE_TIME_BOOTTIME:
579 return &e->boottime;
580
6a0f1f6d
LP
581 case SOURCE_TIME_MONOTONIC:
582 return &e->monotonic;
583
584 case SOURCE_TIME_REALTIME_ALARM:
585 return &e->realtime_alarm;
586
587 case SOURCE_TIME_BOOTTIME_ALARM:
588 return &e->boottime_alarm;
589
590 default:
591 return NULL;
592 }
593}
594
9da4cb2b
LP
595static int event_make_signal_data(
596 sd_event *e,
597 int sig,
598 struct signal_data **ret) {
4807d2d0 599
f95387cd 600 struct epoll_event ev = {};
9da4cb2b
LP
601 struct signal_data *d;
602 bool added = false;
603 sigset_t ss_copy;
604 int64_t priority;
f95387cd
ZJS
605 int r;
606
607 assert(e);
608
f6806734 609 if (event_pid_changed(e))
9da4cb2b 610 return -ECHILD;
f6806734 611
9da4cb2b
LP
612 if (e->signal_sources && e->signal_sources[sig])
613 priority = e->signal_sources[sig]->priority;
614 else
615 priority = 0;
f95387cd 616
9da4cb2b
LP
617 d = hashmap_get(e->signal_data, &priority);
618 if (d) {
619 if (sigismember(&d->sigset, sig) > 0) {
620 if (ret)
621 *ret = d;
622 return 0;
623 }
624 } else {
625 r = hashmap_ensure_allocated(&e->signal_data, &uint64_hash_ops);
626 if (r < 0)
627 return r;
628
629 d = new0(struct signal_data, 1);
630 if (!d)
631 return -ENOMEM;
632
633 d->wakeup = WAKEUP_SIGNAL_DATA;
634 d->fd = -1;
635 d->priority = priority;
636
637 r = hashmap_put(e->signal_data, &d->priority, d);
638 if (r < 0)
639 return r;
f95387cd 640
9da4cb2b
LP
641 added = true;
642 }
643
644 ss_copy = d->sigset;
645 assert_se(sigaddset(&ss_copy, sig) >= 0);
646
647 r = signalfd(d->fd, &ss_copy, SFD_NONBLOCK|SFD_CLOEXEC);
648 if (r < 0) {
649 r = -errno;
650 goto fail;
651 }
652
653 d->sigset = ss_copy;
f95387cd 654
9da4cb2b
LP
655 if (d->fd >= 0) {
656 if (ret)
657 *ret = d;
f95387cd 658 return 0;
9da4cb2b
LP
659 }
660
661 d->fd = r;
f95387cd
ZJS
662
663 ev.events = EPOLLIN;
9da4cb2b 664 ev.data.ptr = d;
f95387cd 665
9da4cb2b
LP
666 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev);
667 if (r < 0) {
668 r = -errno;
669 goto fail;
f95387cd
ZJS
670 }
671
9da4cb2b
LP
672 if (ret)
673 *ret = d;
674
f95387cd 675 return 0;
9da4cb2b
LP
676
677fail:
678 if (added) {
679 d->fd = safe_close(d->fd);
680 hashmap_remove(e->signal_data, &d->priority);
681 free(d);
682 }
683
684 return r;
685}
686
687static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig) {
688 assert(e);
689 assert(d);
690
691 /* Turns off the specified signal in the signal data
692 * object. If the signal mask of the object becomes empty that
693 * way removes it. */
694
695 if (sigismember(&d->sigset, sig) == 0)
696 return;
697
698 assert_se(sigdelset(&d->sigset, sig) >= 0);
699
700 if (sigisemptyset(&d->sigset)) {
701
702 /* If all the mask is all-zero we can get rid of the structure */
703 hashmap_remove(e->signal_data, &d->priority);
704 assert(!d->current);
705 safe_close(d->fd);
706 free(d);
707 return;
708 }
709
710 assert(d->fd >= 0);
711
712 if (signalfd(d->fd, &d->sigset, SFD_NONBLOCK|SFD_CLOEXEC) < 0)
713 log_debug_errno(errno, "Failed to unset signal bit, ignoring: %m");
714}
715
716static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) {
717 struct signal_data *d;
718 static const int64_t zero_priority = 0;
719
720 assert(e);
721
722 /* Rechecks if the specified signal is still something we are
723 * interested in. If not, we'll unmask it, and possibly drop
724 * the signalfd for it. */
725
726 if (sig == SIGCHLD &&
727 e->n_enabled_child_sources > 0)
728 return;
729
730 if (e->signal_sources &&
731 e->signal_sources[sig] &&
732 e->signal_sources[sig]->enabled != SD_EVENT_OFF)
733 return;
734
735 /*
736 * The specified signal might be enabled in three different queues:
737 *
738 * 1) the one that belongs to the priority passed (if it is non-NULL)
739 * 2) the one that belongs to the priority of the event source of the signal (if there is one)
740 * 3) the 0 priority (to cover the SIGCHLD case)
741 *
742 * Hence, let's remove it from all three here.
743 */
744
745 if (priority) {
746 d = hashmap_get(e->signal_data, priority);
747 if (d)
748 event_unmask_signal_data(e, d, sig);
749 }
750
751 if (e->signal_sources && e->signal_sources[sig]) {
752 d = hashmap_get(e->signal_data, &e->signal_sources[sig]->priority);
753 if (d)
754 event_unmask_signal_data(e, d, sig);
755 }
756
757 d = hashmap_get(e->signal_data, &zero_priority);
758 if (d)
759 event_unmask_signal_data(e, d, sig);
f95387cd
ZJS
760}
761
a71fe8b8
LP
762static void source_disconnect(sd_event_source *s) {
763 sd_event *event;
764
fd38203a
LP
765 assert(s);
766
a71fe8b8
LP
767 if (!s->event)
768 return;
15b38f93 769
a71fe8b8 770 assert(s->event->n_sources > 0);
fd38203a 771
a71fe8b8 772 switch (s->type) {
fd38203a 773
a71fe8b8
LP
774 case SOURCE_IO:
775 if (s->io.fd >= 0)
776 source_io_unregister(s);
fd38203a 777
a71fe8b8 778 break;
6a0f1f6d 779
a71fe8b8 780 case SOURCE_TIME_REALTIME:
a8548816 781 case SOURCE_TIME_BOOTTIME:
a71fe8b8
LP
782 case SOURCE_TIME_MONOTONIC:
783 case SOURCE_TIME_REALTIME_ALARM:
784 case SOURCE_TIME_BOOTTIME_ALARM: {
785 struct clock_data *d;
fd38203a 786
a71fe8b8
LP
787 d = event_get_clock_data(s->event, s->type);
788 assert(d);
789
790 prioq_remove(d->earliest, s, &s->time.earliest_index);
791 prioq_remove(d->latest, s, &s->time.latest_index);
212bbb17 792 d->needs_rearm = true;
a71fe8b8
LP
793 break;
794 }
795
796 case SOURCE_SIGNAL:
797 if (s->signal.sig > 0) {
9da4cb2b 798
a71fe8b8
LP
799 if (s->event->signal_sources)
800 s->event->signal_sources[s->signal.sig] = NULL;
4807d2d0 801
9da4cb2b 802 event_gc_signal_data(s->event, &s->priority, s->signal.sig);
6a0f1f6d 803 }
fd38203a 804
a71fe8b8 805 break;
fd38203a 806
a71fe8b8
LP
807 case SOURCE_CHILD:
808 if (s->child.pid > 0) {
809 if (s->enabled != SD_EVENT_OFF) {
810 assert(s->event->n_enabled_child_sources > 0);
811 s->event->n_enabled_child_sources--;
4807d2d0 812 }
fd38203a 813
4a0b58c4 814 (void) hashmap_remove(s->event->child_sources, PID_TO_PTR(s->child.pid));
9da4cb2b 815 event_gc_signal_data(s->event, &s->priority, SIGCHLD);
a71fe8b8 816 }
fd38203a 817
a71fe8b8 818 break;
fd38203a 819
a71fe8b8
LP
820 case SOURCE_DEFER:
821 /* nothing */
822 break;
fd38203a 823
a71fe8b8
LP
824 case SOURCE_POST:
825 set_remove(s->event->post_sources, s);
826 break;
da7e457c 827
a71fe8b8
LP
828 case SOURCE_EXIT:
829 prioq_remove(s->event->exit, s, &s->exit.prioq_index);
830 break;
0eb2e0e3 831
a71fe8b8
LP
832 default:
833 assert_not_reached("Wut? I shouldn't exist.");
834 }
6e9feda3 835
a71fe8b8
LP
836 if (s->pending)
837 prioq_remove(s->event->pending, s, &s->pending_index);
9d3e3aa5 838
a71fe8b8
LP
839 if (s->prepare)
840 prioq_remove(s->event->prepare, s, &s->prepare_index);
fd38203a 841
a71fe8b8 842 event = s->event;
fd38203a 843
a71fe8b8
LP
844 s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID;
845 s->event = NULL;
846 LIST_REMOVE(sources, event->sources, s);
847 event->n_sources--;
fd38203a 848
a71fe8b8
LP
849 if (!s->floating)
850 sd_event_unref(event);
851}
852
853static void source_free(sd_event_source *s) {
854 assert(s);
fd38203a 855
a71fe8b8 856 source_disconnect(s);
356779df 857 free(s->description);
fd38203a
LP
858 free(s);
859}
860
861static int source_set_pending(sd_event_source *s, bool b) {
862 int r;
863
864 assert(s);
6203e07a 865 assert(s->type != SOURCE_EXIT);
fd38203a
LP
866
867 if (s->pending == b)
868 return 0;
869
870 s->pending = b;
871
872 if (b) {
873 s->pending_iteration = s->event->iteration;
874
875 r = prioq_put(s->event->pending, s, &s->pending_index);
876 if (r < 0) {
877 s->pending = false;
878 return r;
879 }
880 } else
881 assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
882
6a0f1f6d
LP
883 if (EVENT_SOURCE_IS_TIME(s->type)) {
884 struct clock_data *d;
885
886 d = event_get_clock_data(s->event, s->type);
887 assert(d);
888
889 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
890 prioq_reshuffle(d->latest, s, &s->time.latest_index);
212bbb17 891 d->needs_rearm = true;
2576a19e
LP
892 }
893
9da4cb2b
LP
894 if (s->type == SOURCE_SIGNAL && !b) {
895 struct signal_data *d;
896
897 d = hashmap_get(s->event->signal_data, &s->priority);
898 if (d && d->current == s)
899 d->current = NULL;
900 }
901
fd38203a
LP
902 return 0;
903}
904
a71fe8b8 905static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) {
fd38203a
LP
906 sd_event_source *s;
907
908 assert(e);
909
910 s = new0(sd_event_source, 1);
911 if (!s)
912 return NULL;
913
da7e457c 914 s->n_ref = 1;
a71fe8b8 915 s->event = e;
4a134c49 916 s->floating = floating;
fd38203a 917 s->type = type;
fd38203a 918 s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
a71fe8b8
LP
919
920 if (!floating)
921 sd_event_ref(e);
fd38203a 922
a71fe8b8 923 LIST_PREPEND(sources, e->sources, s);
15b38f93
LP
924 e->n_sources ++;
925
fd38203a
LP
926 return s;
927}
928
f7262a9f 929_public_ int sd_event_add_io(
fd38203a 930 sd_event *e,
151b9b96 931 sd_event_source **ret,
fd38203a
LP
932 int fd,
933 uint32_t events,
718db961 934 sd_event_io_handler_t callback,
151b9b96 935 void *userdata) {
fd38203a
LP
936
937 sd_event_source *s;
938 int r;
939
305f78bf 940 assert_return(e, -EINVAL);
8ac43fee 941 assert_return(fd >= 0, -EBADF);
2a16a986 942 assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
305f78bf 943 assert_return(callback, -EINVAL);
da7e457c 944 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 945 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 946
a71fe8b8 947 s = source_new(e, !ret, SOURCE_IO);
fd38203a
LP
948 if (!s)
949 return -ENOMEM;
950
9da4cb2b 951 s->wakeup = WAKEUP_EVENT_SOURCE;
fd38203a
LP
952 s->io.fd = fd;
953 s->io.events = events;
954 s->io.callback = callback;
955 s->userdata = userdata;
baf76283 956 s->enabled = SD_EVENT_ON;
fd38203a 957
baf76283 958 r = source_io_register(s, s->enabled, events);
fd38203a
LP
959 if (r < 0) {
960 source_free(s);
050f74f2 961 return r;
fd38203a
LP
962 }
963
a71fe8b8
LP
964 if (ret)
965 *ret = s;
966
fd38203a
LP
967 return 0;
968}
969
52444dc4
LP
970static void initialize_perturb(sd_event *e) {
971 sd_id128_t bootid = {};
972
973 /* When we sleep for longer, we try to realign the wakeup to
974 the same time wihtin each minute/second/250ms, so that
975 events all across the system can be coalesced into a single
976 CPU wakeup. However, let's take some system-specific
977 randomness for this value, so that in a network of systems
978 with synced clocks timer events are distributed a
979 bit. Here, we calculate a perturbation usec offset from the
980 boot ID. */
981
3a43da28 982 if (_likely_(e->perturb != USEC_INFINITY))
52444dc4
LP
983 return;
984
985 if (sd_id128_get_boot(&bootid) >= 0)
986 e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE;
987}
988
fd38203a
LP
989static int event_setup_timer_fd(
990 sd_event *e,
6a0f1f6d
LP
991 struct clock_data *d,
992 clockid_t clock) {
fd38203a
LP
993
994 struct epoll_event ev = {};
995 int r, fd;
996
997 assert(e);
6a0f1f6d 998 assert(d);
fd38203a 999
6a0f1f6d 1000 if (_likely_(d->fd >= 0))
fd38203a
LP
1001 return 0;
1002
6a0f1f6d 1003 fd = timerfd_create(clock, TFD_NONBLOCK|TFD_CLOEXEC);
fd38203a
LP
1004 if (fd < 0)
1005 return -errno;
1006
1007 ev.events = EPOLLIN;
9da4cb2b 1008 ev.data.ptr = d;
fd38203a
LP
1009
1010 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
1011 if (r < 0) {
03e334a1 1012 safe_close(fd);
fd38203a
LP
1013 return -errno;
1014 }
1015
6a0f1f6d 1016 d->fd = fd;
fd38203a
LP
1017 return 0;
1018}
1019
c4f1aff2
TG
1020static int time_exit_callback(sd_event_source *s, uint64_t usec, void *userdata) {
1021 assert(s);
1022
1023 return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
1024}
1025
6a0f1f6d 1026_public_ int sd_event_add_time(
fd38203a 1027 sd_event *e,
151b9b96 1028 sd_event_source **ret,
6a0f1f6d 1029 clockid_t clock,
fd38203a 1030 uint64_t usec,
c2ba3ad6 1031 uint64_t accuracy,
718db961 1032 sd_event_time_handler_t callback,
151b9b96 1033 void *userdata) {
fd38203a 1034
6a0f1f6d 1035 EventSourceType type;
fd38203a 1036 sd_event_source *s;
6a0f1f6d 1037 struct clock_data *d;
fd38203a
LP
1038 int r;
1039
305f78bf 1040 assert_return(e, -EINVAL);
305f78bf
LP
1041 assert_return(usec != (uint64_t) -1, -EINVAL);
1042 assert_return(accuracy != (uint64_t) -1, -EINVAL);
da7e457c 1043 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1044 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 1045
c4f1aff2
TG
1046 if (!callback)
1047 callback = time_exit_callback;
1048
6a0f1f6d 1049 type = clock_to_event_source_type(clock);
15411c0c 1050 assert_return(type >= 0, -EOPNOTSUPP);
6a0f1f6d
LP
1051
1052 d = event_get_clock_data(e, type);
1053 assert(d);
c2ba3ad6 1054
6a0f1f6d
LP
1055 if (!d->earliest) {
1056 d->earliest = prioq_new(earliest_time_prioq_compare);
1057 if (!d->earliest)
c2ba3ad6
LP
1058 return -ENOMEM;
1059 }
fd38203a 1060
6a0f1f6d
LP
1061 if (!d->latest) {
1062 d->latest = prioq_new(latest_time_prioq_compare);
1063 if (!d->latest)
fd38203a
LP
1064 return -ENOMEM;
1065 }
1066
6a0f1f6d
LP
1067 if (d->fd < 0) {
1068 r = event_setup_timer_fd(e, d, clock);
fd38203a
LP
1069 if (r < 0)
1070 return r;
1071 }
1072
a71fe8b8 1073 s = source_new(e, !ret, type);
fd38203a
LP
1074 if (!s)
1075 return -ENOMEM;
1076
1077 s->time.next = usec;
c2ba3ad6 1078 s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy;
fd38203a 1079 s->time.callback = callback;
da7e457c 1080 s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL;
fd38203a 1081 s->userdata = userdata;
baf76283 1082 s->enabled = SD_EVENT_ONESHOT;
fd38203a 1083
e07bbb7c
TG
1084 d->needs_rearm = true;
1085
6a0f1f6d 1086 r = prioq_put(d->earliest, s, &s->time.earliest_index);
c2ba3ad6
LP
1087 if (r < 0)
1088 goto fail;
1089
6a0f1f6d 1090 r = prioq_put(d->latest, s, &s->time.latest_index);
c2ba3ad6
LP
1091 if (r < 0)
1092 goto fail;
fd38203a 1093
a71fe8b8
LP
1094 if (ret)
1095 *ret = s;
1096
fd38203a 1097 return 0;
c2ba3ad6
LP
1098
1099fail:
1100 source_free(s);
1101 return r;
fd38203a
LP
1102}
1103
59bc1fd7
LP
1104static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
1105 assert(s);
1106
1107 return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
1108}
1109
f7262a9f 1110_public_ int sd_event_add_signal(
305f78bf 1111 sd_event *e,
151b9b96 1112 sd_event_source **ret,
305f78bf 1113 int sig,
718db961 1114 sd_event_signal_handler_t callback,
151b9b96 1115 void *userdata) {
305f78bf 1116
fd38203a 1117 sd_event_source *s;
9da4cb2b 1118 struct signal_data *d;
3022d74b 1119 sigset_t ss;
fd38203a
LP
1120 int r;
1121
305f78bf
LP
1122 assert_return(e, -EINVAL);
1123 assert_return(sig > 0, -EINVAL);
1124 assert_return(sig < _NSIG, -EINVAL);
da7e457c 1125 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1126 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 1127
59bc1fd7
LP
1128 if (!callback)
1129 callback = signal_exit_callback;
1130
3022d74b 1131 r = pthread_sigmask(SIG_SETMASK, NULL, &ss);
50e0d56c
LP
1132 if (r != 0)
1133 return -r;
3022d74b
LP
1134
1135 if (!sigismember(&ss, sig))
1136 return -EBUSY;
1137
fd38203a
LP
1138 if (!e->signal_sources) {
1139 e->signal_sources = new0(sd_event_source*, _NSIG);
1140 if (!e->signal_sources)
1141 return -ENOMEM;
1142 } else if (e->signal_sources[sig])
1143 return -EBUSY;
1144
a71fe8b8 1145 s = source_new(e, !ret, SOURCE_SIGNAL);
fd38203a
LP
1146 if (!s)
1147 return -ENOMEM;
1148
1149 s->signal.sig = sig;
1150 s->signal.callback = callback;
1151 s->userdata = userdata;
baf76283 1152 s->enabled = SD_EVENT_ON;
fd38203a
LP
1153
1154 e->signal_sources[sig] = s;
fd38203a 1155
9da4cb2b
LP
1156 r = event_make_signal_data(e, sig, &d);
1157 if (r < 0) {
1158 source_free(s);
1159 return r;
fd38203a
LP
1160 }
1161
f1f00dbb
LP
1162 /* Use the signal name as description for the event source by default */
1163 (void) sd_event_source_set_description(s, signal_to_string(sig));
1164
a71fe8b8
LP
1165 if (ret)
1166 *ret = s;
1167
fd38203a
LP
1168 return 0;
1169}
1170
f7262a9f 1171_public_ int sd_event_add_child(
305f78bf 1172 sd_event *e,
151b9b96 1173 sd_event_source **ret,
305f78bf
LP
1174 pid_t pid,
1175 int options,
718db961 1176 sd_event_child_handler_t callback,
151b9b96 1177 void *userdata) {
305f78bf 1178
fd38203a
LP
1179 sd_event_source *s;
1180 int r;
1181
305f78bf
LP
1182 assert_return(e, -EINVAL);
1183 assert_return(pid > 1, -EINVAL);
1184 assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
1185 assert_return(options != 0, -EINVAL);
1186 assert_return(callback, -EINVAL);
da7e457c 1187 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1188 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 1189
d5099efc 1190 r = hashmap_ensure_allocated(&e->child_sources, NULL);
fd38203a
LP
1191 if (r < 0)
1192 return r;
1193
4a0b58c4 1194 if (hashmap_contains(e->child_sources, PID_TO_PTR(pid)))
fd38203a
LP
1195 return -EBUSY;
1196
a71fe8b8 1197 s = source_new(e, !ret, SOURCE_CHILD);
fd38203a
LP
1198 if (!s)
1199 return -ENOMEM;
1200
1201 s->child.pid = pid;
1202 s->child.options = options;
1203 s->child.callback = callback;
1204 s->userdata = userdata;
baf76283 1205 s->enabled = SD_EVENT_ONESHOT;
fd38203a 1206
4a0b58c4 1207 r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s);
fd38203a
LP
1208 if (r < 0) {
1209 source_free(s);
1210 return r;
1211 }
1212
baf76283 1213 e->n_enabled_child_sources ++;
fd38203a 1214
9da4cb2b
LP
1215 r = event_make_signal_data(e, SIGCHLD, NULL);
1216 if (r < 0) {
1217 e->n_enabled_child_sources--;
1218 source_free(s);
1219 return r;
fd38203a
LP
1220 }
1221
c2ba3ad6
LP
1222 e->need_process_child = true;
1223
a71fe8b8
LP
1224 if (ret)
1225 *ret = s;
1226
fd38203a
LP
1227 return 0;
1228}
1229
f7262a9f 1230_public_ int sd_event_add_defer(
305f78bf 1231 sd_event *e,
151b9b96 1232 sd_event_source **ret,
718db961 1233 sd_event_handler_t callback,
151b9b96 1234 void *userdata) {
305f78bf 1235
fd38203a
LP
1236 sd_event_source *s;
1237 int r;
1238
305f78bf
LP
1239 assert_return(e, -EINVAL);
1240 assert_return(callback, -EINVAL);
da7e457c 1241 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1242 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 1243
a71fe8b8 1244 s = source_new(e, !ret, SOURCE_DEFER);
fd38203a
LP
1245 if (!s)
1246 return -ENOMEM;
1247
1248 s->defer.callback = callback;
1249 s->userdata = userdata;
baf76283 1250 s->enabled = SD_EVENT_ONESHOT;
fd38203a
LP
1251
1252 r = source_set_pending(s, true);
1253 if (r < 0) {
1254 source_free(s);
1255 return r;
1256 }
1257
a71fe8b8
LP
1258 if (ret)
1259 *ret = s;
1260
fd38203a
LP
1261 return 0;
1262}
1263
6e9feda3
LP
1264_public_ int sd_event_add_post(
1265 sd_event *e,
1266 sd_event_source **ret,
1267 sd_event_handler_t callback,
1268 void *userdata) {
1269
1270 sd_event_source *s;
1271 int r;
1272
1273 assert_return(e, -EINVAL);
1274 assert_return(callback, -EINVAL);
6e9feda3
LP
1275 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
1276 assert_return(!event_pid_changed(e), -ECHILD);
1277
d5099efc 1278 r = set_ensure_allocated(&e->post_sources, NULL);
6e9feda3
LP
1279 if (r < 0)
1280 return r;
1281
a71fe8b8 1282 s = source_new(e, !ret, SOURCE_POST);
6e9feda3
LP
1283 if (!s)
1284 return -ENOMEM;
1285
1286 s->post.callback = callback;
1287 s->userdata = userdata;
1288 s->enabled = SD_EVENT_ON;
1289
1290 r = set_put(e->post_sources, s);
1291 if (r < 0) {
1292 source_free(s);
1293 return r;
1294 }
1295
a71fe8b8
LP
1296 if (ret)
1297 *ret = s;
1298
6e9feda3
LP
1299 return 0;
1300}
1301
6203e07a 1302_public_ int sd_event_add_exit(
305f78bf 1303 sd_event *e,
151b9b96 1304 sd_event_source **ret,
718db961 1305 sd_event_handler_t callback,
151b9b96 1306 void *userdata) {
305f78bf 1307
da7e457c
LP
1308 sd_event_source *s;
1309 int r;
1310
1311 assert_return(e, -EINVAL);
1312 assert_return(callback, -EINVAL);
1313 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
1314 assert_return(!event_pid_changed(e), -ECHILD);
1315
6203e07a
LP
1316 if (!e->exit) {
1317 e->exit = prioq_new(exit_prioq_compare);
1318 if (!e->exit)
da7e457c
LP
1319 return -ENOMEM;
1320 }
1321
a71fe8b8 1322 s = source_new(e, !ret, SOURCE_EXIT);
fd38203a 1323 if (!s)
da7e457c 1324 return -ENOMEM;
fd38203a 1325
6203e07a 1326 s->exit.callback = callback;
da7e457c 1327 s->userdata = userdata;
6203e07a 1328 s->exit.prioq_index = PRIOQ_IDX_NULL;
baf76283 1329 s->enabled = SD_EVENT_ONESHOT;
da7e457c 1330
6203e07a 1331 r = prioq_put(s->event->exit, s, &s->exit.prioq_index);
da7e457c
LP
1332 if (r < 0) {
1333 source_free(s);
1334 return r;
1335 }
1336
a71fe8b8
LP
1337 if (ret)
1338 *ret = s;
1339
da7e457c
LP
1340 return 0;
1341}
1342
f7262a9f 1343_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
6680dd6b
LP
1344
1345 if (!s)
1346 return NULL;
da7e457c
LP
1347
1348 assert(s->n_ref >= 1);
1349 s->n_ref++;
fd38203a
LP
1350
1351 return s;
1352}
1353
f7262a9f 1354_public_ sd_event_source* sd_event_source_unref(sd_event_source *s) {
5b1bc83f
LP
1355
1356 if (!s)
1357 return NULL;
fd38203a 1358
da7e457c
LP
1359 assert(s->n_ref >= 1);
1360 s->n_ref--;
1361
12179984
LP
1362 if (s->n_ref <= 0) {
1363 /* Here's a special hack: when we are called from a
1364 * dispatch handler we won't free the event source
1365 * immediately, but we will detach the fd from the
1366 * epoll. This way it is safe for the caller to unref
1367 * the event source and immediately close the fd, but
1368 * we still retain a valid event source object after
1369 * the callback. */
1370
1371 if (s->dispatching) {
1372 if (s->type == SOURCE_IO)
1373 source_io_unregister(s);
a71fe8b8
LP
1374
1375 source_disconnect(s);
12179984
LP
1376 } else
1377 source_free(s);
1378 }
fd38203a
LP
1379
1380 return NULL;
1381}
1382
356779df 1383_public_ int sd_event_source_set_description(sd_event_source *s, const char *description) {
f7f53e9e 1384 assert_return(s, -EINVAL);
f4b2933e 1385 assert_return(!event_pid_changed(s->event), -ECHILD);
f7f53e9e 1386
356779df 1387 return free_and_strdup(&s->description, description);
f7f53e9e
TG
1388}
1389
356779df 1390_public_ int sd_event_source_get_description(sd_event_source *s, const char **description) {
f7f53e9e 1391 assert_return(s, -EINVAL);
356779df 1392 assert_return(description, -EINVAL);
f4b2933e
LP
1393 assert_return(s->description, -ENXIO);
1394 assert_return(!event_pid_changed(s->event), -ECHILD);
f7f53e9e 1395
356779df 1396 *description = s->description;
f7f53e9e
TG
1397 return 0;
1398}
1399
adcc4ca3 1400_public_ sd_event *sd_event_source_get_event(sd_event_source *s) {
305f78bf 1401 assert_return(s, NULL);
eaa3cbef
LP
1402
1403 return s->event;
1404}
1405
f7262a9f 1406_public_ int sd_event_source_get_pending(sd_event_source *s) {
305f78bf 1407 assert_return(s, -EINVAL);
6203e07a 1408 assert_return(s->type != SOURCE_EXIT, -EDOM);
da7e457c 1409 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1410 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1411
1412 return s->pending;
1413}
1414
f7262a9f 1415_public_ int sd_event_source_get_io_fd(sd_event_source *s) {
305f78bf
LP
1416 assert_return(s, -EINVAL);
1417 assert_return(s->type == SOURCE_IO, -EDOM);
1418 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1419
1420 return s->io.fd;
1421}
1422
30caf8f3
LP
1423_public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) {
1424 int r;
1425
1426 assert_return(s, -EINVAL);
8ac43fee 1427 assert_return(fd >= 0, -EBADF);
30caf8f3
LP
1428 assert_return(s->type == SOURCE_IO, -EDOM);
1429 assert_return(!event_pid_changed(s->event), -ECHILD);
1430
1431 if (s->io.fd == fd)
1432 return 0;
1433
1434 if (s->enabled == SD_EVENT_OFF) {
1435 s->io.fd = fd;
1436 s->io.registered = false;
1437 } else {
1438 int saved_fd;
1439
1440 saved_fd = s->io.fd;
1441 assert(s->io.registered);
1442
1443 s->io.fd = fd;
1444 s->io.registered = false;
1445
1446 r = source_io_register(s, s->enabled, s->io.events);
1447 if (r < 0) {
1448 s->io.fd = saved_fd;
1449 s->io.registered = true;
1450 return r;
1451 }
1452
1453 epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, saved_fd, NULL);
1454 }
1455
1456 return 0;
1457}
1458
f7262a9f 1459_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) {
305f78bf
LP
1460 assert_return(s, -EINVAL);
1461 assert_return(events, -EINVAL);
1462 assert_return(s->type == SOURCE_IO, -EDOM);
1463 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1464
1465 *events = s->io.events;
1466 return 0;
1467}
1468
f7262a9f 1469_public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) {
fd38203a
LP
1470 int r;
1471
305f78bf
LP
1472 assert_return(s, -EINVAL);
1473 assert_return(s->type == SOURCE_IO, -EDOM);
2a16a986 1474 assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
da7e457c 1475 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1476 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1477
b63c8d4f
DH
1478 /* edge-triggered updates are never skipped, so we can reset edges */
1479 if (s->io.events == events && !(events & EPOLLET))
fd38203a
LP
1480 return 0;
1481
baf76283 1482 if (s->enabled != SD_EVENT_OFF) {
e4715127 1483 r = source_io_register(s, s->enabled, events);
fd38203a
LP
1484 if (r < 0)
1485 return r;
1486 }
1487
1488 s->io.events = events;
503f39c3 1489 source_set_pending(s, false);
fd38203a
LP
1490
1491 return 0;
1492}
1493
f7262a9f 1494_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) {
305f78bf
LP
1495 assert_return(s, -EINVAL);
1496 assert_return(revents, -EINVAL);
1497 assert_return(s->type == SOURCE_IO, -EDOM);
1498 assert_return(s->pending, -ENODATA);
1499 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1500
1501 *revents = s->io.revents;
1502 return 0;
1503}
1504
f7262a9f 1505_public_ int sd_event_source_get_signal(sd_event_source *s) {
305f78bf
LP
1506 assert_return(s, -EINVAL);
1507 assert_return(s->type == SOURCE_SIGNAL, -EDOM);
1508 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1509
1510 return s->signal.sig;
1511}
1512
31927c16 1513_public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority) {
305f78bf
LP
1514 assert_return(s, -EINVAL);
1515 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1516
1517 return s->priority;
1518}
1519
31927c16 1520_public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) {
9da4cb2b
LP
1521 int r;
1522
305f78bf 1523 assert_return(s, -EINVAL);
da7e457c 1524 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1525 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1526
1527 if (s->priority == priority)
1528 return 0;
1529
9da4cb2b
LP
1530 if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) {
1531 struct signal_data *old, *d;
1532
1533 /* Move us from the signalfd belonging to the old
1534 * priority to the signalfd of the new priority */
1535
1536 assert_se(old = hashmap_get(s->event->signal_data, &s->priority));
1537
1538 s->priority = priority;
1539
1540 r = event_make_signal_data(s->event, s->signal.sig, &d);
1541 if (r < 0) {
1542 s->priority = old->priority;
1543 return r;
1544 }
1545
1546 event_unmask_signal_data(s->event, old, s->signal.sig);
1547 } else
1548 s->priority = priority;
fd38203a
LP
1549
1550 if (s->pending)
c2ba3ad6 1551 prioq_reshuffle(s->event->pending, s, &s->pending_index);
fd38203a
LP
1552
1553 if (s->prepare)
c2ba3ad6 1554 prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
fd38203a 1555
6203e07a
LP
1556 if (s->type == SOURCE_EXIT)
1557 prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
305f78bf 1558
fd38203a
LP
1559 return 0;
1560}
1561
f7262a9f 1562_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
305f78bf
LP
1563 assert_return(s, -EINVAL);
1564 assert_return(m, -EINVAL);
1565 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1566
baf76283 1567 *m = s->enabled;
fd38203a
LP
1568 return 0;
1569}
1570
f7262a9f 1571_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
fd38203a
LP
1572 int r;
1573
305f78bf
LP
1574 assert_return(s, -EINVAL);
1575 assert_return(m == SD_EVENT_OFF || m == SD_EVENT_ON || m == SD_EVENT_ONESHOT, -EINVAL);
305f78bf 1576 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1577
cc567911
LP
1578 /* If we are dead anyway, we are fine with turning off
1579 * sources, but everything else needs to fail. */
1580 if (s->event->state == SD_EVENT_FINISHED)
1581 return m == SD_EVENT_OFF ? 0 : -ESTALE;
1582
baf76283 1583 if (s->enabled == m)
fd38203a
LP
1584 return 0;
1585
baf76283 1586 if (m == SD_EVENT_OFF) {
fd38203a
LP
1587
1588 switch (s->type) {
1589
1590 case SOURCE_IO:
366e6411 1591 source_io_unregister(s);
baf76283 1592 s->enabled = m;
fd38203a
LP
1593 break;
1594
6a0f1f6d 1595 case SOURCE_TIME_REALTIME:
a8548816 1596 case SOURCE_TIME_BOOTTIME:
6a0f1f6d
LP
1597 case SOURCE_TIME_MONOTONIC:
1598 case SOURCE_TIME_REALTIME_ALARM:
1599 case SOURCE_TIME_BOOTTIME_ALARM: {
1600 struct clock_data *d;
fd38203a 1601
baf76283 1602 s->enabled = m;
6a0f1f6d
LP
1603 d = event_get_clock_data(s->event, s->type);
1604 assert(d);
1605
1606 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
1607 prioq_reshuffle(d->latest, s, &s->time.latest_index);
212bbb17 1608 d->needs_rearm = true;
fd38203a 1609 break;
6a0f1f6d 1610 }
fd38203a
LP
1611
1612 case SOURCE_SIGNAL:
baf76283 1613 s->enabled = m;
4807d2d0 1614
9da4cb2b 1615 event_gc_signal_data(s->event, &s->priority, s->signal.sig);
fd38203a
LP
1616 break;
1617
1618 case SOURCE_CHILD:
baf76283 1619 s->enabled = m;
fd38203a 1620
baf76283
LP
1621 assert(s->event->n_enabled_child_sources > 0);
1622 s->event->n_enabled_child_sources--;
fd38203a 1623
9da4cb2b 1624 event_gc_signal_data(s->event, &s->priority, SIGCHLD);
fd38203a
LP
1625 break;
1626
6203e07a 1627 case SOURCE_EXIT:
305f78bf 1628 s->enabled = m;
6203e07a 1629 prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
305f78bf
LP
1630 break;
1631
1632 case SOURCE_DEFER:
6e9feda3 1633 case SOURCE_POST:
baf76283 1634 s->enabled = m;
fd38203a 1635 break;
9d3e3aa5 1636
6a0f1f6d 1637 default:
9d3e3aa5 1638 assert_not_reached("Wut? I shouldn't exist.");
fd38203a
LP
1639 }
1640
1641 } else {
1642 switch (s->type) {
1643
1644 case SOURCE_IO:
1645 r = source_io_register(s, m, s->io.events);
1646 if (r < 0)
1647 return r;
1648
baf76283 1649 s->enabled = m;
fd38203a
LP
1650 break;
1651
6a0f1f6d 1652 case SOURCE_TIME_REALTIME:
a8548816 1653 case SOURCE_TIME_BOOTTIME:
6a0f1f6d
LP
1654 case SOURCE_TIME_MONOTONIC:
1655 case SOURCE_TIME_REALTIME_ALARM:
1656 case SOURCE_TIME_BOOTTIME_ALARM: {
1657 struct clock_data *d;
fd38203a 1658
baf76283 1659 s->enabled = m;
6a0f1f6d
LP
1660 d = event_get_clock_data(s->event, s->type);
1661 assert(d);
1662
1663 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
1664 prioq_reshuffle(d->latest, s, &s->time.latest_index);
212bbb17 1665 d->needs_rearm = true;
fd38203a 1666 break;
6a0f1f6d 1667 }
fd38203a
LP
1668
1669 case SOURCE_SIGNAL:
4807d2d0
ZJS
1670
1671 s->enabled = m;
9da4cb2b
LP
1672
1673 r = event_make_signal_data(s->event, s->signal.sig, NULL);
1674 if (r < 0) {
1675 s->enabled = SD_EVENT_OFF;
1676 event_gc_signal_data(s->event, &s->priority, s->signal.sig);
1677 return r;
1678 }
1679
fd38203a
LP
1680 break;
1681
1682 case SOURCE_CHILD:
4807d2d0 1683
9da4cb2b 1684 if (s->enabled == SD_EVENT_OFF)
4807d2d0 1685 s->event->n_enabled_child_sources++;
7a0d4a3d
DH
1686
1687 s->enabled = m;
9da4cb2b 1688
10edebf6 1689 r = event_make_signal_data(s->event, SIGCHLD, NULL);
9da4cb2b
LP
1690 if (r < 0) {
1691 s->enabled = SD_EVENT_OFF;
1692 s->event->n_enabled_child_sources--;
1693 event_gc_signal_data(s->event, &s->priority, SIGCHLD);
1694 return r;
1695 }
1696
fd38203a
LP
1697 break;
1698
6203e07a 1699 case SOURCE_EXIT:
305f78bf 1700 s->enabled = m;
6203e07a 1701 prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
305f78bf
LP
1702 break;
1703
1704 case SOURCE_DEFER:
6e9feda3 1705 case SOURCE_POST:
baf76283 1706 s->enabled = m;
fd38203a 1707 break;
9d3e3aa5 1708
6a0f1f6d 1709 default:
9d3e3aa5 1710 assert_not_reached("Wut? I shouldn't exist.");
fd38203a
LP
1711 }
1712 }
1713
1714 if (s->pending)
1715 prioq_reshuffle(s->event->pending, s, &s->pending_index);
1716
1717 if (s->prepare)
1718 prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
1719
1720 return 0;
1721}
1722
f7262a9f 1723_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
305f78bf
LP
1724 assert_return(s, -EINVAL);
1725 assert_return(usec, -EINVAL);
6a0f1f6d 1726 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
305f78bf 1727 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1728
1729 *usec = s->time.next;
1730 return 0;
1731}
1732
f7262a9f 1733_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
6a0f1f6d
LP
1734 struct clock_data *d;
1735
305f78bf
LP
1736 assert_return(s, -EINVAL);
1737 assert_return(usec != (uint64_t) -1, -EINVAL);
6a0f1f6d 1738 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
da7e457c 1739 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1740 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1741
fd38203a 1742 s->time.next = usec;
2576a19e 1743
0cc1125a 1744 source_set_pending(s, false);
fd38203a 1745
6a0f1f6d
LP
1746 d = event_get_clock_data(s->event, s->type);
1747 assert(d);
1748
1749 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
1750 prioq_reshuffle(d->latest, s, &s->time.latest_index);
212bbb17 1751 d->needs_rearm = true;
fd38203a
LP
1752
1753 return 0;
1754}
1755
f7262a9f 1756_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
305f78bf
LP
1757 assert_return(s, -EINVAL);
1758 assert_return(usec, -EINVAL);
6a0f1f6d 1759 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
305f78bf
LP
1760 assert_return(!event_pid_changed(s->event), -ECHILD);
1761
1762 *usec = s->time.accuracy;
1763 return 0;
1764}
1765
f7262a9f 1766_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
6a0f1f6d
LP
1767 struct clock_data *d;
1768
305f78bf
LP
1769 assert_return(s, -EINVAL);
1770 assert_return(usec != (uint64_t) -1, -EINVAL);
6a0f1f6d 1771 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
da7e457c 1772 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1773 assert_return(!event_pid_changed(s->event), -ECHILD);
eaa3cbef
LP
1774
1775 if (usec == 0)
1776 usec = DEFAULT_ACCURACY_USEC;
1777
eaa3cbef
LP
1778 s->time.accuracy = usec;
1779
2576a19e
LP
1780 source_set_pending(s, false);
1781
6a0f1f6d
LP
1782 d = event_get_clock_data(s->event, s->type);
1783 assert(d);
1784
1785 prioq_reshuffle(d->latest, s, &s->time.latest_index);
212bbb17 1786 d->needs_rearm = true;
6a0f1f6d
LP
1787
1788 return 0;
1789}
1790
1791_public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock) {
1792 assert_return(s, -EINVAL);
1793 assert_return(clock, -EINVAL);
1794 assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
1795 assert_return(!event_pid_changed(s->event), -ECHILD);
eaa3cbef 1796
6a0f1f6d 1797 *clock = event_source_type_to_clock(s->type);
eaa3cbef
LP
1798 return 0;
1799}
1800
f7262a9f 1801_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
4bee8012
LP
1802 assert_return(s, -EINVAL);
1803 assert_return(pid, -EINVAL);
1804 assert_return(s->type == SOURCE_CHILD, -EDOM);
1805 assert_return(!event_pid_changed(s->event), -ECHILD);
1806
1807 *pid = s->child.pid;
1808 return 0;
1809}
1810
718db961 1811_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
fd38203a
LP
1812 int r;
1813
da7e457c 1814 assert_return(s, -EINVAL);
6203e07a 1815 assert_return(s->type != SOURCE_EXIT, -EDOM);
da7e457c
LP
1816 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
1817 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1818
1819 if (s->prepare == callback)
1820 return 0;
1821
1822 if (callback && s->prepare) {
1823 s->prepare = callback;
1824 return 0;
1825 }
1826
1827 r = prioq_ensure_allocated(&s->event->prepare, prepare_prioq_compare);
1828 if (r < 0)
1829 return r;
1830
1831 s->prepare = callback;
1832
1833 if (callback) {
1834 r = prioq_put(s->event->prepare, s, &s->prepare_index);
1835 if (r < 0)
1836 return r;
1837 } else
1838 prioq_remove(s->event->prepare, s, &s->prepare_index);
1839
1840 return 0;
1841}
1842
f7262a9f 1843_public_ void* sd_event_source_get_userdata(sd_event_source *s) {
da7e457c 1844 assert_return(s, NULL);
fd38203a
LP
1845
1846 return s->userdata;
1847}
1848
8f726607
LP
1849_public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata) {
1850 void *ret;
1851
1852 assert_return(s, NULL);
1853
1854 ret = s->userdata;
1855 s->userdata = userdata;
1856
1857 return ret;
1858}
1859
c2ba3ad6
LP
1860static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) {
1861 usec_t c;
1862 assert(e);
1863 assert(a <= b);
1864
1865 if (a <= 0)
1866 return 0;
1867
1868 if (b <= a + 1)
1869 return a;
1870
52444dc4
LP
1871 initialize_perturb(e);
1872
c2ba3ad6
LP
1873 /*
1874 Find a good time to wake up again between times a and b. We
1875 have two goals here:
1876
1877 a) We want to wake up as seldom as possible, hence prefer
1878 later times over earlier times.
1879
1880 b) But if we have to wake up, then let's make sure to
1881 dispatch as much as possible on the entire system.
1882
1883 We implement this by waking up everywhere at the same time
850516e0 1884 within any given minute if we can, synchronised via the
c2ba3ad6 1885 perturbation value determined from the boot ID. If we can't,
ba276c81
LP
1886 then we try to find the same spot in every 10s, then 1s and
1887 then 250ms step. Otherwise, we pick the last possible time
1888 to wake up.
c2ba3ad6
LP
1889 */
1890
850516e0
LP
1891 c = (b / USEC_PER_MINUTE) * USEC_PER_MINUTE + e->perturb;
1892 if (c >= b) {
1893 if (_unlikely_(c < USEC_PER_MINUTE))
1894 return b;
1895
1896 c -= USEC_PER_MINUTE;
1897 }
1898
ba276c81
LP
1899 if (c >= a)
1900 return c;
1901
1902 c = (b / (USEC_PER_SEC*10)) * (USEC_PER_SEC*10) + (e->perturb % (USEC_PER_SEC*10));
1903 if (c >= b) {
1904 if (_unlikely_(c < USEC_PER_SEC*10))
1905 return b;
1906
1907 c -= USEC_PER_SEC*10;
1908 }
1909
850516e0
LP
1910 if (c >= a)
1911 return c;
1912
1913 c = (b / USEC_PER_SEC) * USEC_PER_SEC + (e->perturb % USEC_PER_SEC);
c2ba3ad6
LP
1914 if (c >= b) {
1915 if (_unlikely_(c < USEC_PER_SEC))
1916 return b;
1917
1918 c -= USEC_PER_SEC;
1919 }
1920
1921 if (c >= a)
1922 return c;
1923
1924 c = (b / (USEC_PER_MSEC*250)) * (USEC_PER_MSEC*250) + (e->perturb % (USEC_PER_MSEC*250));
1925 if (c >= b) {
1926 if (_unlikely_(c < USEC_PER_MSEC*250))
1927 return b;
1928
1929 c -= USEC_PER_MSEC*250;
1930 }
1931
1932 if (c >= a)
1933 return c;
1934
1935 return b;
1936}
1937
fd38203a
LP
1938static int event_arm_timer(
1939 sd_event *e,
6a0f1f6d 1940 struct clock_data *d) {
fd38203a
LP
1941
1942 struct itimerspec its = {};
c2ba3ad6
LP
1943 sd_event_source *a, *b;
1944 usec_t t;
fd38203a
LP
1945 int r;
1946
cde93897 1947 assert(e);
6a0f1f6d 1948 assert(d);
fd38203a 1949
d06441da 1950 if (!d->needs_rearm)
212bbb17
TG
1951 return 0;
1952 else
1953 d->needs_rearm = false;
1954
6a0f1f6d 1955 a = prioq_peek(d->earliest);
72aedc1e
LP
1956 if (!a || a->enabled == SD_EVENT_OFF) {
1957
6a0f1f6d 1958 if (d->fd < 0)
c57b5ca3
LP
1959 return 0;
1960
3a43da28 1961 if (d->next == USEC_INFINITY)
72aedc1e
LP
1962 return 0;
1963
1964 /* disarm */
6a0f1f6d 1965 r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL);
72aedc1e
LP
1966 if (r < 0)
1967 return r;
1968
3a43da28 1969 d->next = USEC_INFINITY;
fd38203a 1970 return 0;
72aedc1e 1971 }
fd38203a 1972
6a0f1f6d 1973 b = prioq_peek(d->latest);
baf76283 1974 assert_se(b && b->enabled != SD_EVENT_OFF);
c2ba3ad6
LP
1975
1976 t = sleep_between(e, a->time.next, b->time.next + b->time.accuracy);
6a0f1f6d 1977 if (d->next == t)
fd38203a
LP
1978 return 0;
1979
6a0f1f6d 1980 assert_se(d->fd >= 0);
fd38203a 1981
c2ba3ad6 1982 if (t == 0) {
fd38203a
LP
1983 /* We don' want to disarm here, just mean some time looooong ago. */
1984 its.it_value.tv_sec = 0;
1985 its.it_value.tv_nsec = 1;
1986 } else
c2ba3ad6 1987 timespec_store(&its.it_value, t);
fd38203a 1988
6a0f1f6d 1989 r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL);
fd38203a 1990 if (r < 0)
cde93897 1991 return -errno;
fd38203a 1992
6a0f1f6d 1993 d->next = t;
fd38203a
LP
1994 return 0;
1995}
1996
9a800b56 1997static int process_io(sd_event *e, sd_event_source *s, uint32_t revents) {
fd38203a
LP
1998 assert(e);
1999 assert(s);
2000 assert(s->type == SOURCE_IO);
2001
9a800b56
LP
2002 /* If the event source was already pending, we just OR in the
2003 * new revents, otherwise we reset the value. The ORing is
2004 * necessary to handle EPOLLONESHOT events properly where
2005 * readability might happen independently of writability, and
2006 * we need to keep track of both */
2007
2008 if (s->pending)
2009 s->io.revents |= revents;
2010 else
2011 s->io.revents = revents;
fd38203a 2012
fd38203a
LP
2013 return source_set_pending(s, true);
2014}
2015
72aedc1e 2016static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) {
fd38203a
LP
2017 uint64_t x;
2018 ssize_t ss;
2019
2020 assert(e);
da7e457c 2021 assert(fd >= 0);
72aedc1e 2022
305f78bf 2023 assert_return(events == EPOLLIN, -EIO);
fd38203a
LP
2024
2025 ss = read(fd, &x, sizeof(x));
2026 if (ss < 0) {
2027 if (errno == EAGAIN || errno == EINTR)
2028 return 0;
2029
2030 return -errno;
2031 }
2032
8d35dae7 2033 if (_unlikely_(ss != sizeof(x)))
fd38203a
LP
2034 return -EIO;
2035
cde93897 2036 if (next)
3a43da28 2037 *next = USEC_INFINITY;
72aedc1e 2038
fd38203a
LP
2039 return 0;
2040}
2041
305f78bf
LP
2042static int process_timer(
2043 sd_event *e,
2044 usec_t n,
6a0f1f6d 2045 struct clock_data *d) {
305f78bf 2046
fd38203a
LP
2047 sd_event_source *s;
2048 int r;
2049
2050 assert(e);
6a0f1f6d 2051 assert(d);
fd38203a
LP
2052
2053 for (;;) {
6a0f1f6d 2054 s = prioq_peek(d->earliest);
fd38203a
LP
2055 if (!s ||
2056 s->time.next > n ||
baf76283 2057 s->enabled == SD_EVENT_OFF ||
fd38203a
LP
2058 s->pending)
2059 break;
2060
2061 r = source_set_pending(s, true);
2062 if (r < 0)
2063 return r;
2064
6a0f1f6d
LP
2065 prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
2066 prioq_reshuffle(d->latest, s, &s->time.latest_index);
e07bbb7c 2067 d->needs_rearm = true;
fd38203a
LP
2068 }
2069
2070 return 0;
2071}
2072
2073static int process_child(sd_event *e) {
2074 sd_event_source *s;
2075 Iterator i;
2076 int r;
2077
2078 assert(e);
2079
c2ba3ad6
LP
2080 e->need_process_child = false;
2081
fd38203a
LP
2082 /*
2083 So, this is ugly. We iteratively invoke waitid() with P_PID
2084 + WNOHANG for each PID we wait for, instead of using
2085 P_ALL. This is because we only want to get child
2086 information of very specific child processes, and not all
2087 of them. We might not have processed the SIGCHLD even of a
2088 previous invocation and we don't want to maintain a
2089 unbounded *per-child* event queue, hence we really don't
2090 want anything flushed out of the kernel's queue that we
2091 don't care about. Since this is O(n) this means that if you
2092 have a lot of processes you probably want to handle SIGCHLD
2093 yourself.
08cd1552
LP
2094
2095 We do not reap the children here (by using WNOWAIT), this
2096 is only done after the event source is dispatched so that
2097 the callback still sees the process as a zombie.
fd38203a
LP
2098 */
2099
2100 HASHMAP_FOREACH(s, e->child_sources, i) {
2101 assert(s->type == SOURCE_CHILD);
2102
2103 if (s->pending)
2104 continue;
2105
baf76283 2106 if (s->enabled == SD_EVENT_OFF)
fd38203a
LP
2107 continue;
2108
2109 zero(s->child.siginfo);
08cd1552
LP
2110 r = waitid(P_PID, s->child.pid, &s->child.siginfo,
2111 WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options);
fd38203a
LP
2112 if (r < 0)
2113 return -errno;
2114
2115 if (s->child.siginfo.si_pid != 0) {
08cd1552
LP
2116 bool zombie =
2117 s->child.siginfo.si_code == CLD_EXITED ||
2118 s->child.siginfo.si_code == CLD_KILLED ||
2119 s->child.siginfo.si_code == CLD_DUMPED;
2120
2121 if (!zombie && (s->child.options & WEXITED)) {
2122 /* If the child isn't dead then let's
2123 * immediately remove the state change
2124 * from the queue, since there's no
2125 * benefit in leaving it queued */
2126
2127 assert(s->child.options & (WSTOPPED|WCONTINUED));
2128 waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED)));
2129 }
2130
fd38203a
LP
2131 r = source_set_pending(s, true);
2132 if (r < 0)
2133 return r;
2134 }
2135 }
2136
fd38203a
LP
2137 return 0;
2138}
2139
9da4cb2b 2140static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
fd38203a 2141 bool read_one = false;
fd38203a
LP
2142 int r;
2143
da7e457c 2144 assert(e);
305f78bf 2145 assert_return(events == EPOLLIN, -EIO);
fd38203a 2146
9da4cb2b
LP
2147 /* If there's a signal queued on this priority and SIGCHLD is
2148 on this priority too, then make sure to recheck the
2149 children we watch. This is because we only ever dequeue
2150 the first signal per priority, and if we dequeue one, and
2151 SIGCHLD might be enqueued later we wouldn't know, but we
2152 might have higher priority children we care about hence we
2153 need to check that explicitly. */
2154
2155 if (sigismember(&d->sigset, SIGCHLD))
2156 e->need_process_child = true;
2157
2158 /* If there's already an event source pending for this
2159 * priority we don't read another */
2160 if (d->current)
2161 return 0;
2162
fd38203a 2163 for (;;) {
0eb2e0e3 2164 struct signalfd_siginfo si;
7057bd99 2165 ssize_t n;
92daebc0 2166 sd_event_source *s = NULL;
fd38203a 2167
9da4cb2b 2168 n = read(d->fd, &si, sizeof(si));
7057bd99 2169 if (n < 0) {
fd38203a
LP
2170 if (errno == EAGAIN || errno == EINTR)
2171 return read_one;
2172
2173 return -errno;
2174 }
2175
7057bd99 2176 if (_unlikely_(n != sizeof(si)))
fd38203a
LP
2177 return -EIO;
2178
7057bd99
ZJS
2179 assert(si.ssi_signo < _NSIG);
2180
fd38203a
LP
2181 read_one = true;
2182
92daebc0
LP
2183 if (e->signal_sources)
2184 s = e->signal_sources[si.ssi_signo];
92daebc0
LP
2185 if (!s)
2186 continue;
9da4cb2b
LP
2187 if (s->pending)
2188 continue;
fd38203a
LP
2189
2190 s->signal.siginfo = si;
9da4cb2b
LP
2191 d->current = s;
2192
fd38203a
LP
2193 r = source_set_pending(s, true);
2194 if (r < 0)
2195 return r;
9da4cb2b
LP
2196
2197 return 1;
fd38203a 2198 }
fd38203a
LP
2199}
2200
2201static int source_dispatch(sd_event_source *s) {
fe8245eb 2202 int r = 0;
fd38203a
LP
2203
2204 assert(s);
6203e07a 2205 assert(s->pending || s->type == SOURCE_EXIT);
fd38203a 2206
6203e07a 2207 if (s->type != SOURCE_DEFER && s->type != SOURCE_EXIT) {
da7e457c
LP
2208 r = source_set_pending(s, false);
2209 if (r < 0)
2210 return r;
2211 }
fd38203a 2212
6e9feda3
LP
2213 if (s->type != SOURCE_POST) {
2214 sd_event_source *z;
2215 Iterator i;
2216
2217 /* If we execute a non-post source, let's mark all
2218 * post sources as pending */
2219
2220 SET_FOREACH(z, s->event->post_sources, i) {
2221 if (z->enabled == SD_EVENT_OFF)
2222 continue;
2223
2224 r = source_set_pending(z, true);
2225 if (r < 0)
2226 return r;
2227 }
2228 }
2229
baf76283
LP
2230 if (s->enabled == SD_EVENT_ONESHOT) {
2231 r = sd_event_source_set_enabled(s, SD_EVENT_OFF);
fd38203a
LP
2232 if (r < 0)
2233 return r;
2234 }
2235
12179984 2236 s->dispatching = true;
b7484e2a 2237
fd38203a
LP
2238 switch (s->type) {
2239
2240 case SOURCE_IO:
2241 r = s->io.callback(s, s->io.fd, s->io.revents, s->userdata);
2242 break;
2243
6a0f1f6d 2244 case SOURCE_TIME_REALTIME:
a8548816 2245 case SOURCE_TIME_BOOTTIME:
6a0f1f6d
LP
2246 case SOURCE_TIME_MONOTONIC:
2247 case SOURCE_TIME_REALTIME_ALARM:
2248 case SOURCE_TIME_BOOTTIME_ALARM:
fd38203a
LP
2249 r = s->time.callback(s, s->time.next, s->userdata);
2250 break;
2251
2252 case SOURCE_SIGNAL:
2253 r = s->signal.callback(s, &s->signal.siginfo, s->userdata);
2254 break;
2255
08cd1552
LP
2256 case SOURCE_CHILD: {
2257 bool zombie;
2258
2259 zombie = s->child.siginfo.si_code == CLD_EXITED ||
2260 s->child.siginfo.si_code == CLD_KILLED ||
2261 s->child.siginfo.si_code == CLD_DUMPED;
2262
fd38203a 2263 r = s->child.callback(s, &s->child.siginfo, s->userdata);
08cd1552
LP
2264
2265 /* Now, reap the PID for good. */
2266 if (zombie)
2267 waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
2268
fd38203a 2269 break;
08cd1552 2270 }
fd38203a
LP
2271
2272 case SOURCE_DEFER:
2273 r = s->defer.callback(s, s->userdata);
2274 break;
da7e457c 2275
6e9feda3
LP
2276 case SOURCE_POST:
2277 r = s->post.callback(s, s->userdata);
2278 break;
2279
6203e07a
LP
2280 case SOURCE_EXIT:
2281 r = s->exit.callback(s, s->userdata);
da7e457c 2282 break;
9d3e3aa5
LP
2283
2284 case SOURCE_WATCHDOG:
a71fe8b8 2285 case _SOURCE_EVENT_SOURCE_TYPE_MAX:
9f2a50a3 2286 case _SOURCE_EVENT_SOURCE_TYPE_INVALID:
9d3e3aa5 2287 assert_not_reached("Wut? I shouldn't exist.");
fd38203a
LP
2288 }
2289
12179984
LP
2290 s->dispatching = false;
2291
752bbf75 2292 if (r < 0) {
356779df 2293 if (s->description)
da927ba9 2294 log_debug_errno(r, "Event source '%s' returned error, disabling: %m", s->description);
752bbf75 2295 else
da927ba9 2296 log_debug_errno(r, "Event source %p returned error, disabling: %m", s);
752bbf75 2297 }
12179984
LP
2298
2299 if (s->n_ref == 0)
2300 source_free(s);
2301 else if (r < 0)
6203e07a 2302 sd_event_source_set_enabled(s, SD_EVENT_OFF);
b7484e2a 2303
6203e07a 2304 return 1;
fd38203a
LP
2305}
2306
2307static int event_prepare(sd_event *e) {
2308 int r;
2309
2310 assert(e);
2311
2312 for (;;) {
2313 sd_event_source *s;
2314
2315 s = prioq_peek(e->prepare);
baf76283 2316 if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF)
fd38203a
LP
2317 break;
2318
2319 s->prepare_iteration = e->iteration;
2320 r = prioq_reshuffle(e->prepare, s, &s->prepare_index);
2321 if (r < 0)
2322 return r;
2323
2324 assert(s->prepare);
12179984
LP
2325
2326 s->dispatching = true;
fd38203a 2327 r = s->prepare(s, s->userdata);
12179984
LP
2328 s->dispatching = false;
2329
752bbf75 2330 if (r < 0) {
356779df 2331 if (s->description)
da927ba9 2332 log_debug_errno(r, "Prepare callback of event source '%s' returned error, disabling: %m", s->description);
752bbf75 2333 else
da927ba9 2334 log_debug_errno(r, "Prepare callback of event source %p returned error, disabling: %m", s);
752bbf75 2335 }
fd38203a 2336
12179984
LP
2337 if (s->n_ref == 0)
2338 source_free(s);
2339 else if (r < 0)
2340 sd_event_source_set_enabled(s, SD_EVENT_OFF);
fd38203a
LP
2341 }
2342
2343 return 0;
2344}
2345
6203e07a 2346static int dispatch_exit(sd_event *e) {
da7e457c
LP
2347 sd_event_source *p;
2348 int r;
2349
2350 assert(e);
2351
6203e07a 2352 p = prioq_peek(e->exit);
baf76283 2353 if (!p || p->enabled == SD_EVENT_OFF) {
da7e457c
LP
2354 e->state = SD_EVENT_FINISHED;
2355 return 0;
2356 }
2357
2358 sd_event_ref(e);
2359 e->iteration++;
6203e07a 2360 e->state = SD_EVENT_EXITING;
da7e457c
LP
2361
2362 r = source_dispatch(p);
2363
2b0c9ef7 2364 e->state = SD_EVENT_INITIAL;
da7e457c
LP
2365 sd_event_unref(e);
2366
2367 return r;
2368}
2369
c2ba3ad6
LP
2370static sd_event_source* event_next_pending(sd_event *e) {
2371 sd_event_source *p;
2372
da7e457c
LP
2373 assert(e);
2374
c2ba3ad6
LP
2375 p = prioq_peek(e->pending);
2376 if (!p)
2377 return NULL;
2378
baf76283 2379 if (p->enabled == SD_EVENT_OFF)
c2ba3ad6
LP
2380 return NULL;
2381
2382 return p;
2383}
2384
cde93897
LP
2385static int arm_watchdog(sd_event *e) {
2386 struct itimerspec its = {};
2387 usec_t t;
2388 int r;
2389
2390 assert(e);
2391 assert(e->watchdog_fd >= 0);
2392
2393 t = sleep_between(e,
2394 e->watchdog_last + (e->watchdog_period / 2),
2395 e->watchdog_last + (e->watchdog_period * 3 / 4));
2396
2397 timespec_store(&its.it_value, t);
2398
75145780
LP
2399 /* Make sure we never set the watchdog to 0, which tells the
2400 * kernel to disable it. */
2401 if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
2402 its.it_value.tv_nsec = 1;
2403
cde93897
LP
2404 r = timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL);
2405 if (r < 0)
2406 return -errno;
2407
2408 return 0;
2409}
2410
2411static int process_watchdog(sd_event *e) {
2412 assert(e);
2413
2414 if (!e->watchdog)
2415 return 0;
2416
2417 /* Don't notify watchdog too often */
2418 if (e->watchdog_last + e->watchdog_period / 4 > e->timestamp.monotonic)
2419 return 0;
2420
2421 sd_notify(false, "WATCHDOG=1");
2422 e->watchdog_last = e->timestamp.monotonic;
2423
2424 return arm_watchdog(e);
2425}
2426
c45a5a74
TG
2427_public_ int sd_event_prepare(sd_event *e) {
2428 int r;
fd38203a 2429
da7e457c
LP
2430 assert_return(e, -EINVAL);
2431 assert_return(!event_pid_changed(e), -ECHILD);
2432 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
2b0c9ef7 2433 assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
da7e457c 2434
6203e07a 2435 if (e->exit_requested)
c45a5a74 2436 goto pending;
fd38203a
LP
2437
2438 e->iteration++;
2439
2440 r = event_prepare(e);
2441 if (r < 0)
c45a5a74 2442 return r;
fd38203a 2443
6a0f1f6d
LP
2444 r = event_arm_timer(e, &e->realtime);
2445 if (r < 0)
c45a5a74 2446 return r;
6a0f1f6d 2447
a8548816
TG
2448 r = event_arm_timer(e, &e->boottime);
2449 if (r < 0)
c45a5a74 2450 return r;
a8548816 2451
6a0f1f6d
LP
2452 r = event_arm_timer(e, &e->monotonic);
2453 if (r < 0)
c45a5a74 2454 return r;
6a0f1f6d
LP
2455
2456 r = event_arm_timer(e, &e->realtime_alarm);
1b5995b0 2457 if (r < 0)
c45a5a74 2458 return r;
fd38203a 2459
6a0f1f6d 2460 r = event_arm_timer(e, &e->boottime_alarm);
1b5995b0 2461 if (r < 0)
c45a5a74 2462 return r;
fd38203a 2463
1b5995b0 2464 if (event_next_pending(e) || e->need_process_child)
c45a5a74
TG
2465 goto pending;
2466
2b0c9ef7 2467 e->state = SD_EVENT_ARMED;
c45a5a74
TG
2468
2469 return 0;
2470
2471pending:
2b0c9ef7 2472 e->state = SD_EVENT_ARMED;
6d148a84
TG
2473 r = sd_event_wait(e, 0);
2474 if (r == 0)
2b0c9ef7 2475 e->state = SD_EVENT_ARMED;
6d148a84
TG
2476
2477 return r;
c45a5a74
TG
2478}
2479
2480_public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
2481 struct epoll_event *ev_queue;
2482 unsigned ev_queue_max;
2483 int r, m, i;
2484
2485 assert_return(e, -EINVAL);
2486 assert_return(!event_pid_changed(e), -ECHILD);
2487 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
2b0c9ef7 2488 assert_return(e->state == SD_EVENT_ARMED, -EBUSY);
c45a5a74
TG
2489
2490 if (e->exit_requested) {
2491 e->state = SD_EVENT_PENDING;
2492 return 1;
2493 }
6a0f1f6d 2494
1c724e9e 2495 ev_queue_max = MAX(e->n_sources, 1u);
15b38f93 2496 ev_queue = newa(struct epoll_event, ev_queue_max);
fd38203a 2497
15b38f93 2498 m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max,
c2ba3ad6 2499 timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
da7e457c 2500 if (m < 0) {
c45a5a74
TG
2501 if (errno == EINTR) {
2502 e->state = SD_EVENT_PENDING;
2503 return 1;
2504 }
2505
2506 r = -errno;
da7e457c
LP
2507 goto finish;
2508 }
fd38203a 2509
46e8c825 2510 dual_timestamp_get(&e->timestamp);
6a0f1f6d 2511 e->timestamp_boottime = now(CLOCK_BOOTTIME);
fd38203a
LP
2512
2513 for (i = 0; i < m; i++) {
2514
9da4cb2b 2515 if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG))
cde93897 2516 r = flush_timer(e, e->watchdog_fd, ev_queue[i].events, NULL);
9da4cb2b
LP
2517 else {
2518 WakeupType *t = ev_queue[i].data.ptr;
2519
2520 switch (*t) {
2521
2522 case WAKEUP_EVENT_SOURCE:
2523 r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events);
2524 break;
fd38203a 2525
9da4cb2b
LP
2526 case WAKEUP_CLOCK_DATA: {
2527 struct clock_data *d = ev_queue[i].data.ptr;
2528 r = flush_timer(e, d->fd, ev_queue[i].events, &d->next);
2529 break;
2530 }
2531
2532 case WAKEUP_SIGNAL_DATA:
2533 r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events);
2534 break;
2535
2536 default:
2537 assert_not_reached("Invalid wake-up pointer");
2538 }
2539 }
fd38203a 2540 if (r < 0)
da7e457c 2541 goto finish;
fd38203a
LP
2542 }
2543
cde93897
LP
2544 r = process_watchdog(e);
2545 if (r < 0)
2546 goto finish;
2547
6a0f1f6d
LP
2548 r = process_timer(e, e->timestamp.realtime, &e->realtime);
2549 if (r < 0)
2550 goto finish;
2551
a8548816
TG
2552 r = process_timer(e, e->timestamp_boottime, &e->boottime);
2553 if (r < 0)
2554 goto finish;
2555
6a0f1f6d
LP
2556 r = process_timer(e, e->timestamp.monotonic, &e->monotonic);
2557 if (r < 0)
2558 goto finish;
2559
2560 r = process_timer(e, e->timestamp.realtime, &e->realtime_alarm);
fd38203a 2561 if (r < 0)
da7e457c 2562 goto finish;
fd38203a 2563
6a0f1f6d 2564 r = process_timer(e, e->timestamp_boottime, &e->boottime_alarm);
fd38203a 2565 if (r < 0)
da7e457c 2566 goto finish;
fd38203a 2567
c2ba3ad6 2568 if (e->need_process_child) {
fd38203a
LP
2569 r = process_child(e);
2570 if (r < 0)
da7e457c 2571 goto finish;
fd38203a
LP
2572 }
2573
c45a5a74
TG
2574 if (event_next_pending(e)) {
2575 e->state = SD_EVENT_PENDING;
2576
2577 return 1;
da7e457c
LP
2578 }
2579
c45a5a74 2580 r = 0;
fd38203a 2581
da7e457c 2582finish:
2b0c9ef7 2583 e->state = SD_EVENT_INITIAL;
da7e457c
LP
2584
2585 return r;
fd38203a
LP
2586}
2587
c45a5a74
TG
2588_public_ int sd_event_dispatch(sd_event *e) {
2589 sd_event_source *p;
2590 int r;
2591
2592 assert_return(e, -EINVAL);
2593 assert_return(!event_pid_changed(e), -ECHILD);
2594 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
2595 assert_return(e->state == SD_EVENT_PENDING, -EBUSY);
2596
2597 if (e->exit_requested)
2598 return dispatch_exit(e);
2599
2600 p = event_next_pending(e);
2601 if (p) {
2602 sd_event_ref(e);
2603
2604 e->state = SD_EVENT_RUNNING;
2605 r = source_dispatch(p);
2b0c9ef7 2606 e->state = SD_EVENT_INITIAL;
c45a5a74
TG
2607
2608 sd_event_unref(e);
2609
2610 return r;
2611 }
2612
2b0c9ef7 2613 e->state = SD_EVENT_INITIAL;
c45a5a74
TG
2614
2615 return 1;
2616}
2617
2618_public_ int sd_event_run(sd_event *e, uint64_t timeout) {
2619 int r;
2620
2621 assert_return(e, -EINVAL);
2622 assert_return(!event_pid_changed(e), -ECHILD);
2623 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
2b0c9ef7 2624 assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
c45a5a74
TG
2625
2626 r = sd_event_prepare(e);
53bac4e0
LP
2627 if (r == 0)
2628 /* There was nothing? Then wait... */
2629 r = sd_event_wait(e, timeout);
c45a5a74 2630
02d30981 2631 if (r > 0) {
53bac4e0 2632 /* There's something now, then let's dispatch it */
02d30981
TG
2633 r = sd_event_dispatch(e);
2634 if (r < 0)
2635 return r;
53bac4e0
LP
2636
2637 return 1;
2638 }
2639
2640 return r;
c45a5a74
TG
2641}
2642
f7262a9f 2643_public_ int sd_event_loop(sd_event *e) {
fd38203a
LP
2644 int r;
2645
da7e457c
LP
2646 assert_return(e, -EINVAL);
2647 assert_return(!event_pid_changed(e), -ECHILD);
2b0c9ef7 2648 assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
da7e457c
LP
2649
2650 sd_event_ref(e);
fd38203a 2651
da7e457c 2652 while (e->state != SD_EVENT_FINISHED) {
fd38203a
LP
2653 r = sd_event_run(e, (uint64_t) -1);
2654 if (r < 0)
da7e457c 2655 goto finish;
fd38203a
LP
2656 }
2657
6203e07a 2658 r = e->exit_code;
da7e457c
LP
2659
2660finish:
2661 sd_event_unref(e);
2662 return r;
fd38203a
LP
2663}
2664
9b364545
TG
2665_public_ int sd_event_get_fd(sd_event *e) {
2666
2667 assert_return(e, -EINVAL);
2668 assert_return(!event_pid_changed(e), -ECHILD);
2669
2670 return e->epoll_fd;
2671}
2672
f7262a9f 2673_public_ int sd_event_get_state(sd_event *e) {
da7e457c
LP
2674 assert_return(e, -EINVAL);
2675 assert_return(!event_pid_changed(e), -ECHILD);
2676
2677 return e->state;
2678}
2679
6203e07a 2680_public_ int sd_event_get_exit_code(sd_event *e, int *code) {
da7e457c 2681 assert_return(e, -EINVAL);
6203e07a 2682 assert_return(code, -EINVAL);
da7e457c 2683 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 2684
6203e07a
LP
2685 if (!e->exit_requested)
2686 return -ENODATA;
2687
2688 *code = e->exit_code;
2689 return 0;
fd38203a
LP
2690}
2691
6203e07a 2692_public_ int sd_event_exit(sd_event *e, int code) {
da7e457c
LP
2693 assert_return(e, -EINVAL);
2694 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
2695 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 2696
6203e07a
LP
2697 e->exit_requested = true;
2698 e->exit_code = code;
2699
fd38203a
LP
2700 return 0;
2701}
46e8c825 2702
6a0f1f6d 2703_public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
46e8c825
LP
2704 assert_return(e, -EINVAL);
2705 assert_return(usec, -EINVAL);
46e8c825
LP
2706 assert_return(!event_pid_changed(e), -ECHILD);
2707
38a03f06
LP
2708 if (!dual_timestamp_is_set(&e->timestamp)) {
2709 /* Implicitly fall back to now() if we never ran
2710 * before and thus have no cached time. */
2711 *usec = now(clock);
2712 return 1;
2713 }
46e8c825 2714
6a0f1f6d
LP
2715 switch (clock) {
2716
2717 case CLOCK_REALTIME:
2718 case CLOCK_REALTIME_ALARM:
2719 *usec = e->timestamp.realtime;
2720 break;
2721
2722 case CLOCK_MONOTONIC:
2723 *usec = e->timestamp.monotonic;
2724 break;
2725
a8548816 2726 case CLOCK_BOOTTIME:
6a0f1f6d
LP
2727 case CLOCK_BOOTTIME_ALARM:
2728 *usec = e->timestamp_boottime;
2729 break;
2730 }
46e8c825 2731
46e8c825
LP
2732 return 0;
2733}
afc6adb5
LP
2734
2735_public_ int sd_event_default(sd_event **ret) {
2736
ec202eae 2737 static thread_local sd_event *default_event = NULL;
39883f62 2738 sd_event *e = NULL;
afc6adb5
LP
2739 int r;
2740
2741 if (!ret)
2742 return !!default_event;
2743
2744 if (default_event) {
2745 *ret = sd_event_ref(default_event);
2746 return 0;
2747 }
2748
2749 r = sd_event_new(&e);
2750 if (r < 0)
2751 return r;
2752
2753 e->default_event_ptr = &default_event;
2754 e->tid = gettid();
2755 default_event = e;
2756
2757 *ret = e;
2758 return 1;
2759}
2760
2761_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) {
2762 assert_return(e, -EINVAL);
2763 assert_return(tid, -EINVAL);
76b54375 2764 assert_return(!event_pid_changed(e), -ECHILD);
afc6adb5 2765
76b54375
LP
2766 if (e->tid != 0) {
2767 *tid = e->tid;
2768 return 0;
2769 }
2770
2771 return -ENXIO;
afc6adb5 2772}
cde93897
LP
2773
2774_public_ int sd_event_set_watchdog(sd_event *e, int b) {
2775 int r;
2776
2777 assert_return(e, -EINVAL);
8f726607 2778 assert_return(!event_pid_changed(e), -ECHILD);
cde93897
LP
2779
2780 if (e->watchdog == !!b)
2781 return e->watchdog;
2782
2783 if (b) {
2784 struct epoll_event ev = {};
cde93897 2785
09812eb7
LP
2786 r = sd_watchdog_enabled(false, &e->watchdog_period);
2787 if (r <= 0)
cde93897 2788 return r;
cde93897
LP
2789
2790 /* Issue first ping immediately */
2791 sd_notify(false, "WATCHDOG=1");
2792 e->watchdog_last = now(CLOCK_MONOTONIC);
2793
2794 e->watchdog_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
2795 if (e->watchdog_fd < 0)
2796 return -errno;
2797
2798 r = arm_watchdog(e);
2799 if (r < 0)
2800 goto fail;
2801
2802 ev.events = EPOLLIN;
2803 ev.data.ptr = INT_TO_PTR(SOURCE_WATCHDOG);
2804
2805 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev);
2806 if (r < 0) {
2807 r = -errno;
2808 goto fail;
2809 }
2810
2811 } else {
2812 if (e->watchdog_fd >= 0) {
2813 epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, e->watchdog_fd, NULL);
03e334a1 2814 e->watchdog_fd = safe_close(e->watchdog_fd);
cde93897
LP
2815 }
2816 }
2817
2818 e->watchdog = !!b;
2819 return e->watchdog;
2820
2821fail:
03e334a1 2822 e->watchdog_fd = safe_close(e->watchdog_fd);
cde93897
LP
2823 return r;
2824}
8f726607
LP
2825
2826_public_ int sd_event_get_watchdog(sd_event *e) {
2827 assert_return(e, -EINVAL);
2828 assert_return(!event_pid_changed(e), -ECHILD);
2829
2830 return e->watchdog;
2831}