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