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