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