]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/sd-event.c
event: be more conservative when returning errors from event handler callbacks
[thirdparty/systemd.git] / src / libsystemd-bus / 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
afc6adb5 26#include "sd-id128.h"
cde93897 27#include "sd-daemon.h"
fd38203a 28#include "macro.h"
fd38203a
LP
29#include "prioq.h"
30#include "hashmap.h"
31#include "util.h"
32#include "time-util.h"
afc6adb5 33#include "missing.h"
fd38203a
LP
34
35#include "sd-event.h"
36
37#define EPOLL_QUEUE_MAX 64
c2ba3ad6 38#define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC)
fd38203a
LP
39
40typedef enum EventSourceType {
41 SOURCE_IO,
42 SOURCE_MONOTONIC,
43 SOURCE_REALTIME,
44 SOURCE_SIGNAL,
45 SOURCE_CHILD,
da7e457c 46 SOURCE_DEFER,
6203e07a 47 SOURCE_EXIT,
cde93897 48 SOURCE_WATCHDOG
fd38203a
LP
49} EventSourceType;
50
51struct sd_event_source {
da7e457c 52 unsigned n_ref;
fd38203a
LP
53
54 sd_event *event;
55 void *userdata;
718db961 56 sd_event_handler_t prepare;
fd38203a
LP
57
58 EventSourceType type:4;
baf76283 59 int enabled:3;
fd38203a
LP
60 bool pending:1;
61
62 int priority;
63 unsigned pending_index;
64 unsigned prepare_index;
65 unsigned pending_iteration;
66 unsigned prepare_iteration;
67
68 union {
69 struct {
718db961 70 sd_event_io_handler_t callback;
fd38203a
LP
71 int fd;
72 uint32_t events;
73 uint32_t revents;
74 bool registered:1;
75 } io;
76 struct {
718db961 77 sd_event_time_handler_t callback;
c2ba3ad6
LP
78 usec_t next, accuracy;
79 unsigned earliest_index;
80 unsigned latest_index;
fd38203a
LP
81 } time;
82 struct {
718db961 83 sd_event_signal_handler_t callback;
fd38203a
LP
84 struct signalfd_siginfo siginfo;
85 int sig;
86 } signal;
87 struct {
718db961 88 sd_event_child_handler_t callback;
fd38203a
LP
89 siginfo_t siginfo;
90 pid_t pid;
91 int options;
92 } child;
93 struct {
718db961 94 sd_event_handler_t callback;
fd38203a 95 } defer;
da7e457c 96 struct {
718db961 97 sd_event_handler_t callback;
da7e457c 98 unsigned prioq_index;
6203e07a 99 } exit;
fd38203a
LP
100 };
101};
102
103struct sd_event {
da7e457c 104 unsigned n_ref;
fd38203a
LP
105
106 int epoll_fd;
107 int signal_fd;
108 int realtime_fd;
109 int monotonic_fd;
cde93897 110 int watchdog_fd;
fd38203a
LP
111
112 Prioq *pending;
113 Prioq *prepare;
c2ba3ad6
LP
114
115 /* For both clocks we maintain two priority queues each, one
116 * ordered for the earliest times the events may be
117 * dispatched, and one ordered by the latest times they must
118 * have been dispatched. The range between the top entries in
119 * the two prioqs is the time window we can freely schedule
120 * wakeups in */
121 Prioq *monotonic_earliest;
122 Prioq *monotonic_latest;
123 Prioq *realtime_earliest;
124 Prioq *realtime_latest;
fd38203a 125
da7e457c
LP
126 usec_t realtime_next, monotonic_next;
127 usec_t perturb;
128
fd38203a
LP
129 sigset_t sigset;
130 sd_event_source **signal_sources;
131
132 Hashmap *child_sources;
baf76283 133 unsigned n_enabled_child_sources;
fd38203a 134
6203e07a 135 Prioq *exit;
fd38203a 136
da7e457c 137 pid_t original_pid;
c2ba3ad6 138
da7e457c 139 unsigned iteration;
46e8c825 140 dual_timestamp timestamp;
da7e457c 141 int state;
eaa3cbef 142
6203e07a 143 bool exit_requested:1;
da7e457c 144 bool need_process_child:1;
cde93897 145 bool watchdog:1;
afc6adb5 146
6203e07a
LP
147 int exit_code;
148
afc6adb5
LP
149 pid_t tid;
150 sd_event **default_event_ptr;
cde93897
LP
151
152 usec_t watchdog_last, watchdog_period;
fd38203a
LP
153};
154
155static int pending_prioq_compare(const void *a, const void *b) {
156 const sd_event_source *x = a, *y = b;
157
158 assert(x->pending);
159 assert(y->pending);
160
baf76283
LP
161 /* Enabled ones first */
162 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 163 return -1;
baf76283 164 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
165 return 1;
166
167 /* Lower priority values first */
168 if (x->priority < y->priority)
169 return -1;
170 if (x->priority > y->priority)
171 return 1;
172
173 /* Older entries first */
174 if (x->pending_iteration < y->pending_iteration)
175 return -1;
176 if (x->pending_iteration > y->pending_iteration)
177 return 1;
178
179 /* Stability for the rest */
180 if (x < y)
181 return -1;
dfcd88f6 182 if (x > y)
fd38203a
LP
183 return 1;
184
185 return 0;
186}
187
188static int prepare_prioq_compare(const void *a, const void *b) {
189 const sd_event_source *x = a, *y = b;
190
191 assert(x->prepare);
192 assert(y->prepare);
193
194 /* Move most recently prepared ones last, so that we can stop
195 * preparing as soon as we hit one that has already been
196 * prepared in the current iteration */
197 if (x->prepare_iteration < y->prepare_iteration)
198 return -1;
199 if (x->prepare_iteration > y->prepare_iteration)
200 return 1;
201
baf76283
LP
202 /* Enabled ones first */
203 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 204 return -1;
baf76283 205 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
206 return 1;
207
208 /* Lower priority values first */
209 if (x->priority < y->priority)
210 return -1;
211 if (x->priority > y->priority)
212 return 1;
213
214 /* Stability for the rest */
215 if (x < y)
216 return -1;
dfcd88f6 217 if (x > y)
fd38203a
LP
218 return 1;
219
220 return 0;
221}
222
c2ba3ad6 223static int earliest_time_prioq_compare(const void *a, const void *b) {
fd38203a
LP
224 const sd_event_source *x = a, *y = b;
225
226 assert(x->type == SOURCE_MONOTONIC || x->type == SOURCE_REALTIME);
227 assert(y->type == SOURCE_MONOTONIC || y->type == SOURCE_REALTIME);
228
baf76283
LP
229 /* Enabled ones first */
230 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
fd38203a 231 return -1;
baf76283 232 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
fd38203a
LP
233 return 1;
234
235 /* Move the pending ones to the end */
236 if (!x->pending && y->pending)
237 return -1;
238 if (x->pending && !y->pending)
239 return 1;
240
241 /* Order by time */
242 if (x->time.next < y->time.next)
243 return -1;
244 if (x->time.next > y->time.next)
a99badf5 245 return 1;
fd38203a
LP
246
247 /* Stability for the rest */
248 if (x < y)
249 return -1;
dfcd88f6 250 if (x > y)
fd38203a
LP
251 return 1;
252
253 return 0;
254}
255
c2ba3ad6
LP
256static int latest_time_prioq_compare(const void *a, const void *b) {
257 const sd_event_source *x = a, *y = b;
258
da7e457c
LP
259 assert((x->type == SOURCE_MONOTONIC && y->type == SOURCE_MONOTONIC) ||
260 (x->type == SOURCE_REALTIME && y->type == SOURCE_REALTIME));
c2ba3ad6 261
baf76283
LP
262 /* Enabled ones first */
263 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
c2ba3ad6 264 return -1;
baf76283 265 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
c2ba3ad6
LP
266 return 1;
267
268 /* Move the pending ones to the end */
269 if (!x->pending && y->pending)
270 return -1;
271 if (x->pending && !y->pending)
272 return 1;
273
274 /* Order by time */
275 if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
276 return -1;
277 if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
a99badf5 278 return 1;
c2ba3ad6
LP
279
280 /* Stability for the rest */
281 if (x < y)
282 return -1;
283 if (x > y)
284 return 1;
285
286 return 0;
287}
288
6203e07a 289static int exit_prioq_compare(const void *a, const void *b) {
da7e457c
LP
290 const sd_event_source *x = a, *y = b;
291
6203e07a
LP
292 assert(x->type == SOURCE_EXIT);
293 assert(y->type == SOURCE_EXIT);
da7e457c 294
baf76283
LP
295 /* Enabled ones first */
296 if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
da7e457c 297 return -1;
baf76283 298 if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
da7e457c
LP
299 return 1;
300
301 /* Lower priority values first */
302 if (x->priority < y->priority)
303 return -1;
304 if (x->priority > y->priority)
305 return 1;
306
307 /* Stability for the rest */
308 if (x < y)
309 return -1;
310 if (x > y)
311 return 1;
312
313 return 0;
314}
315
fd38203a
LP
316static void event_free(sd_event *e) {
317 assert(e);
318
afc6adb5
LP
319 if (e->default_event_ptr)
320 *(e->default_event_ptr) = NULL;
321
fd38203a
LP
322 if (e->epoll_fd >= 0)
323 close_nointr_nofail(e->epoll_fd);
324
325 if (e->signal_fd >= 0)
326 close_nointr_nofail(e->signal_fd);
327
328 if (e->realtime_fd >= 0)
329 close_nointr_nofail(e->realtime_fd);
330
331 if (e->monotonic_fd >= 0)
332 close_nointr_nofail(e->monotonic_fd);
333
cde93897
LP
334 if (e->watchdog_fd >= 0)
335 close_nointr_nofail(e->watchdog_fd);
336
fd38203a
LP
337 prioq_free(e->pending);
338 prioq_free(e->prepare);
c2ba3ad6
LP
339 prioq_free(e->monotonic_earliest);
340 prioq_free(e->monotonic_latest);
341 prioq_free(e->realtime_earliest);
342 prioq_free(e->realtime_latest);
6203e07a 343 prioq_free(e->exit);
fd38203a
LP
344
345 free(e->signal_sources);
346
347 hashmap_free(e->child_sources);
348 free(e);
349}
350
f7262a9f 351_public_ int sd_event_new(sd_event** ret) {
fd38203a
LP
352 sd_event *e;
353 int r;
354
305f78bf 355 assert_return(ret, -EINVAL);
fd38203a
LP
356
357 e = new0(sd_event, 1);
358 if (!e)
359 return -ENOMEM;
360
da7e457c 361 e->n_ref = 1;
cde93897 362 e->signal_fd = e->realtime_fd = e->monotonic_fd = e->watchdog_fd = e->epoll_fd = -1;
fd38203a 363 e->realtime_next = e->monotonic_next = (usec_t) -1;
eaa3cbef 364 e->original_pid = getpid();
fd38203a
LP
365
366 assert_se(sigemptyset(&e->sigset) == 0);
367
368 e->pending = prioq_new(pending_prioq_compare);
369 if (!e->pending) {
370 r = -ENOMEM;
371 goto fail;
372 }
373
374 e->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
375 if (e->epoll_fd < 0) {
376 r = -errno;
377 goto fail;
378 }
379
380 *ret = e;
381 return 0;
382
383fail:
384 event_free(e);
385 return r;
386}
387
f7262a9f 388_public_ sd_event* sd_event_ref(sd_event *e) {
305f78bf 389 assert_return(e, NULL);
fd38203a 390
da7e457c
LP
391 assert(e->n_ref >= 1);
392 e->n_ref++;
fd38203a
LP
393
394 return e;
395}
396
f7262a9f 397_public_ sd_event* sd_event_unref(sd_event *e) {
5b1bc83f
LP
398
399 if (!e)
400 return NULL;
fd38203a 401
da7e457c
LP
402 assert(e->n_ref >= 1);
403 e->n_ref--;
404
405 if (e->n_ref <= 0)
fd38203a
LP
406 event_free(e);
407
408 return NULL;
409}
410
eaa3cbef
LP
411static bool event_pid_changed(sd_event *e) {
412 assert(e);
413
414 /* We don't support people creating am event loop and keeping
415 * it around over a fork(). Let's complain. */
416
417 return e->original_pid != getpid();
418}
419
fd38203a
LP
420static int source_io_unregister(sd_event_source *s) {
421 int r;
422
423 assert(s);
424 assert(s->type == SOURCE_IO);
425
426 if (!s->io.registered)
427 return 0;
428
429 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL);
430 if (r < 0)
431 return -errno;
432
433 s->io.registered = false;
434 return 0;
435}
436
305f78bf
LP
437static int source_io_register(
438 sd_event_source *s,
439 int enabled,
440 uint32_t events) {
441
fd38203a
LP
442 struct epoll_event ev = {};
443 int r;
444
445 assert(s);
446 assert(s->type == SOURCE_IO);
baf76283 447 assert(enabled != SD_EVENT_OFF);
fd38203a
LP
448
449 ev.events = events;
450 ev.data.ptr = s;
451
baf76283 452 if (enabled == SD_EVENT_ONESHOT)
fd38203a
LP
453 ev.events |= EPOLLONESHOT;
454
455 if (s->io.registered)
456 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev);
457 else
458 r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_ADD, s->io.fd, &ev);
459
460 if (r < 0)
461 return -errno;
462
463 s->io.registered = true;
464
465 return 0;
466}
467
468static void source_free(sd_event_source *s) {
469 assert(s);
470
471 if (s->event) {
472 switch (s->type) {
473
474 case SOURCE_IO:
475 if (s->io.fd >= 0)
476 source_io_unregister(s);
477
478 break;
479
480 case SOURCE_MONOTONIC:
c2ba3ad6
LP
481 prioq_remove(s->event->monotonic_earliest, s, &s->time.earliest_index);
482 prioq_remove(s->event->monotonic_latest, s, &s->time.latest_index);
fd38203a
LP
483 break;
484
485 case SOURCE_REALTIME:
c2ba3ad6
LP
486 prioq_remove(s->event->realtime_earliest, s, &s->time.earliest_index);
487 prioq_remove(s->event->realtime_latest, s, &s->time.latest_index);
fd38203a
LP
488 break;
489
490 case SOURCE_SIGNAL:
491 if (s->signal.sig > 0) {
baf76283 492 if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0)
fd38203a
LP
493 assert_se(sigdelset(&s->event->sigset, s->signal.sig) == 0);
494
495 if (s->event->signal_sources)
496 s->event->signal_sources[s->signal.sig] = NULL;
497 }
498
499 break;
500
501 case SOURCE_CHILD:
502 if (s->child.pid > 0) {
baf76283
LP
503 if (s->enabled != SD_EVENT_OFF) {
504 assert(s->event->n_enabled_child_sources > 0);
505 s->event->n_enabled_child_sources--;
fd38203a
LP
506 }
507
508 if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD])
509 assert_se(sigdelset(&s->event->sigset, SIGCHLD) == 0);
510
511 hashmap_remove(s->event->child_sources, INT_TO_PTR(s->child.pid));
512 }
513
514 break;
da7e457c 515
0eb2e0e3
ZJS
516 case SOURCE_DEFER:
517 /* nothing */
518 break;
519
6203e07a
LP
520 case SOURCE_EXIT:
521 prioq_remove(s->event->exit, s, &s->exit.prioq_index);
da7e457c 522 break;
fd38203a
LP
523 }
524
525 if (s->pending)
526 prioq_remove(s->event->pending, s, &s->pending_index);
527
528 if (s->prepare)
529 prioq_remove(s->event->prepare, s, &s->prepare_index);
530
531 sd_event_unref(s->event);
532 }
533
534 free(s);
535}
536
537static int source_set_pending(sd_event_source *s, bool b) {
538 int r;
539
540 assert(s);
6203e07a 541 assert(s->type != SOURCE_EXIT);
fd38203a
LP
542
543 if (s->pending == b)
544 return 0;
545
546 s->pending = b;
547
548 if (b) {
549 s->pending_iteration = s->event->iteration;
550
551 r = prioq_put(s->event->pending, s, &s->pending_index);
552 if (r < 0) {
553 s->pending = false;
554 return r;
555 }
556 } else
557 assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
558
2576a19e
LP
559 if (s->type == SOURCE_REALTIME) {
560 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
561 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
562 } else if (s->type == SOURCE_MONOTONIC) {
563 prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
564 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
565 }
566
fd38203a
LP
567 return 0;
568}
569
570static sd_event_source *source_new(sd_event *e, EventSourceType type) {
571 sd_event_source *s;
572
573 assert(e);
574
575 s = new0(sd_event_source, 1);
576 if (!s)
577 return NULL;
578
da7e457c 579 s->n_ref = 1;
fd38203a
LP
580 s->event = sd_event_ref(e);
581 s->type = type;
fd38203a
LP
582 s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
583
584 return s;
585}
586
f7262a9f 587_public_ int sd_event_add_io(
fd38203a
LP
588 sd_event *e,
589 int fd,
590 uint32_t events,
718db961 591 sd_event_io_handler_t callback,
fd38203a
LP
592 void *userdata,
593 sd_event_source **ret) {
594
595 sd_event_source *s;
596 int r;
597
305f78bf
LP
598 assert_return(e, -EINVAL);
599 assert_return(fd >= 0, -EINVAL);
2a16a986 600 assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
305f78bf
LP
601 assert_return(callback, -EINVAL);
602 assert_return(ret, -EINVAL);
da7e457c 603 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 604 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
605
606 s = source_new(e, SOURCE_IO);
607 if (!s)
608 return -ENOMEM;
609
610 s->io.fd = fd;
611 s->io.events = events;
612 s->io.callback = callback;
613 s->userdata = userdata;
baf76283 614 s->enabled = SD_EVENT_ON;
fd38203a 615
baf76283 616 r = source_io_register(s, s->enabled, events);
fd38203a
LP
617 if (r < 0) {
618 source_free(s);
619 return -errno;
620 }
621
622 *ret = s;
623 return 0;
624}
625
626static int event_setup_timer_fd(
627 sd_event *e,
628 EventSourceType type,
629 int *timer_fd,
630 clockid_t id) {
631
632 struct epoll_event ev = {};
633 int r, fd;
c2ba3ad6 634 sd_id128_t bootid;
fd38203a
LP
635
636 assert(e);
637 assert(timer_fd);
638
639 if (_likely_(*timer_fd >= 0))
640 return 0;
641
642 fd = timerfd_create(id, TFD_NONBLOCK|TFD_CLOEXEC);
643 if (fd < 0)
644 return -errno;
645
646 ev.events = EPOLLIN;
647 ev.data.ptr = INT_TO_PTR(type);
648
649 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
650 if (r < 0) {
651 close_nointr_nofail(fd);
652 return -errno;
653 }
654
c2ba3ad6 655 /* When we sleep for longer, we try to realign the wakeup to
850516e0
LP
656 the same time wihtin each minute/second/250ms, so that
657 events all across the system can be coalesced into a single
658 CPU wakeup. However, let's take some system-specific
659 randomness for this value, so that in a network of systems
660 with synced clocks timer events are distributed a
661 bit. Here, we calculate a perturbation usec offset from the
662 boot ID. */
c2ba3ad6
LP
663
664 if (sd_id128_get_boot(&bootid) >= 0)
850516e0 665 e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE;
c2ba3ad6 666
fd38203a
LP
667 *timer_fd = fd;
668 return 0;
669}
670
671static int event_add_time_internal(
672 sd_event *e,
673 EventSourceType type,
674 int *timer_fd,
675 clockid_t id,
c2ba3ad6
LP
676 Prioq **earliest,
677 Prioq **latest,
fd38203a 678 uint64_t usec,
c2ba3ad6 679 uint64_t accuracy,
718db961 680 sd_event_time_handler_t callback,
fd38203a
LP
681 void *userdata,
682 sd_event_source **ret) {
683
684 sd_event_source *s;
685 int r;
686
305f78bf
LP
687 assert_return(e, -EINVAL);
688 assert_return(callback, -EINVAL);
689 assert_return(ret, -EINVAL);
690 assert_return(usec != (uint64_t) -1, -EINVAL);
691 assert_return(accuracy != (uint64_t) -1, -EINVAL);
da7e457c 692 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 693 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
694
695 assert(timer_fd);
c2ba3ad6
LP
696 assert(earliest);
697 assert(latest);
698
699 if (!*earliest) {
700 *earliest = prioq_new(earliest_time_prioq_compare);
701 if (!*earliest)
702 return -ENOMEM;
703 }
fd38203a 704
c2ba3ad6
LP
705 if (!*latest) {
706 *latest = prioq_new(latest_time_prioq_compare);
707 if (!*latest)
fd38203a
LP
708 return -ENOMEM;
709 }
710
711 if (*timer_fd < 0) {
712 r = event_setup_timer_fd(e, type, timer_fd, id);
713 if (r < 0)
714 return r;
715 }
716
717 s = source_new(e, type);
718 if (!s)
719 return -ENOMEM;
720
721 s->time.next = usec;
c2ba3ad6 722 s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy;
fd38203a 723 s->time.callback = callback;
da7e457c 724 s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL;
fd38203a 725 s->userdata = userdata;
baf76283 726 s->enabled = SD_EVENT_ONESHOT;
fd38203a 727
c2ba3ad6
LP
728 r = prioq_put(*earliest, s, &s->time.earliest_index);
729 if (r < 0)
730 goto fail;
731
732 r = prioq_put(*latest, s, &s->time.latest_index);
733 if (r < 0)
734 goto fail;
fd38203a
LP
735
736 *ret = s;
737 return 0;
c2ba3ad6
LP
738
739fail:
740 source_free(s);
741 return r;
fd38203a
LP
742}
743
f7262a9f
ZJS
744_public_ int sd_event_add_monotonic(sd_event *e,
745 uint64_t usec,
746 uint64_t accuracy,
718db961 747 sd_event_time_handler_t callback,
f7262a9f
ZJS
748 void *userdata,
749 sd_event_source **ret) {
750
c2ba3ad6 751 return event_add_time_internal(e, SOURCE_MONOTONIC, &e->monotonic_fd, CLOCK_MONOTONIC, &e->monotonic_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
fd38203a
LP
752}
753
f7262a9f
ZJS
754_public_ int sd_event_add_realtime(sd_event *e,
755 uint64_t usec,
756 uint64_t accuracy,
718db961 757 sd_event_time_handler_t callback,
f7262a9f
ZJS
758 void *userdata,
759 sd_event_source **ret) {
760
c2ba3ad6 761 return event_add_time_internal(e, SOURCE_REALTIME, &e->realtime_fd, CLOCK_REALTIME, &e->realtime_earliest, &e->monotonic_latest, usec, accuracy, callback, userdata, ret);
fd38203a
LP
762}
763
764static int event_update_signal_fd(sd_event *e) {
765 struct epoll_event ev = {};
766 bool add_to_epoll;
767 int r;
768
769 assert(e);
770
771 add_to_epoll = e->signal_fd < 0;
772
773 r = signalfd(e->signal_fd, &e->sigset, SFD_NONBLOCK|SFD_CLOEXEC);
774 if (r < 0)
775 return -errno;
776
777 e->signal_fd = r;
778
779 if (!add_to_epoll)
780 return 0;
781
782 ev.events = EPOLLIN;
783 ev.data.ptr = INT_TO_PTR(SOURCE_SIGNAL);
784
785 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->signal_fd, &ev);
786 if (r < 0) {
787 close_nointr_nofail(e->signal_fd);
788 e->signal_fd = -1;
789
790 return -errno;
791 }
792
793 return 0;
794}
795
f7262a9f 796_public_ int sd_event_add_signal(
305f78bf
LP
797 sd_event *e,
798 int sig,
718db961 799 sd_event_signal_handler_t callback,
305f78bf
LP
800 void *userdata,
801 sd_event_source **ret) {
802
fd38203a
LP
803 sd_event_source *s;
804 int r;
805
305f78bf
LP
806 assert_return(e, -EINVAL);
807 assert_return(sig > 0, -EINVAL);
808 assert_return(sig < _NSIG, -EINVAL);
809 assert_return(callback, -EINVAL);
810 assert_return(ret, -EINVAL);
da7e457c 811 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 812 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
813
814 if (!e->signal_sources) {
815 e->signal_sources = new0(sd_event_source*, _NSIG);
816 if (!e->signal_sources)
817 return -ENOMEM;
818 } else if (e->signal_sources[sig])
819 return -EBUSY;
820
821 s = source_new(e, SOURCE_SIGNAL);
822 if (!s)
823 return -ENOMEM;
824
825 s->signal.sig = sig;
826 s->signal.callback = callback;
827 s->userdata = userdata;
baf76283 828 s->enabled = SD_EVENT_ON;
fd38203a
LP
829
830 e->signal_sources[sig] = s;
831 assert_se(sigaddset(&e->sigset, sig) == 0);
832
baf76283 833 if (sig != SIGCHLD || e->n_enabled_child_sources == 0) {
fd38203a
LP
834 r = event_update_signal_fd(e);
835 if (r < 0) {
836 source_free(s);
837 return r;
838 }
839 }
840
841 *ret = s;
842 return 0;
843}
844
f7262a9f 845_public_ int sd_event_add_child(
305f78bf
LP
846 sd_event *e,
847 pid_t pid,
848 int options,
718db961 849 sd_event_child_handler_t callback,
305f78bf
LP
850 void *userdata,
851 sd_event_source **ret) {
852
fd38203a
LP
853 sd_event_source *s;
854 int r;
855
305f78bf
LP
856 assert_return(e, -EINVAL);
857 assert_return(pid > 1, -EINVAL);
858 assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
859 assert_return(options != 0, -EINVAL);
860 assert_return(callback, -EINVAL);
861 assert_return(ret, -EINVAL);
da7e457c 862 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 863 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
864
865 r = hashmap_ensure_allocated(&e->child_sources, trivial_hash_func, trivial_compare_func);
866 if (r < 0)
867 return r;
868
869 if (hashmap_contains(e->child_sources, INT_TO_PTR(pid)))
870 return -EBUSY;
871
872 s = source_new(e, SOURCE_CHILD);
873 if (!s)
874 return -ENOMEM;
875
876 s->child.pid = pid;
877 s->child.options = options;
878 s->child.callback = callback;
879 s->userdata = userdata;
baf76283 880 s->enabled = SD_EVENT_ONESHOT;
fd38203a
LP
881
882 r = hashmap_put(e->child_sources, INT_TO_PTR(pid), s);
883 if (r < 0) {
884 source_free(s);
885 return r;
886 }
887
baf76283 888 e->n_enabled_child_sources ++;
fd38203a
LP
889
890 assert_se(sigaddset(&e->sigset, SIGCHLD) == 0);
891
892 if (!e->signal_sources || !e->signal_sources[SIGCHLD]) {
893 r = event_update_signal_fd(e);
894 if (r < 0) {
895 source_free(s);
896 return -errno;
897 }
898 }
899
c2ba3ad6
LP
900 e->need_process_child = true;
901
fd38203a
LP
902 *ret = s;
903 return 0;
904}
905
f7262a9f 906_public_ int sd_event_add_defer(
305f78bf 907 sd_event *e,
718db961 908 sd_event_handler_t callback,
305f78bf
LP
909 void *userdata,
910 sd_event_source **ret) {
911
fd38203a
LP
912 sd_event_source *s;
913 int r;
914
305f78bf
LP
915 assert_return(e, -EINVAL);
916 assert_return(callback, -EINVAL);
917 assert_return(ret, -EINVAL);
da7e457c 918 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 919 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a
LP
920
921 s = source_new(e, SOURCE_DEFER);
922 if (!s)
923 return -ENOMEM;
924
925 s->defer.callback = callback;
926 s->userdata = userdata;
baf76283 927 s->enabled = SD_EVENT_ONESHOT;
fd38203a
LP
928
929 r = source_set_pending(s, true);
930 if (r < 0) {
931 source_free(s);
932 return r;
933 }
934
935 *ret = s;
936 return 0;
937}
938
6203e07a 939_public_ int sd_event_add_exit(
305f78bf 940 sd_event *e,
718db961 941 sd_event_handler_t callback,
305f78bf
LP
942 void *userdata,
943 sd_event_source **ret) {
944
da7e457c
LP
945 sd_event_source *s;
946 int r;
947
948 assert_return(e, -EINVAL);
949 assert_return(callback, -EINVAL);
305f78bf 950 assert_return(ret, -EINVAL);
da7e457c
LP
951 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
952 assert_return(!event_pid_changed(e), -ECHILD);
953
6203e07a
LP
954 if (!e->exit) {
955 e->exit = prioq_new(exit_prioq_compare);
956 if (!e->exit)
da7e457c
LP
957 return -ENOMEM;
958 }
959
6203e07a 960 s = source_new(e, SOURCE_EXIT);
fd38203a 961 if (!s)
da7e457c 962 return -ENOMEM;
fd38203a 963
6203e07a 964 s->exit.callback = callback;
da7e457c 965 s->userdata = userdata;
6203e07a 966 s->exit.prioq_index = PRIOQ_IDX_NULL;
baf76283 967 s->enabled = SD_EVENT_ONESHOT;
da7e457c 968
6203e07a 969 r = prioq_put(s->event->exit, s, &s->exit.prioq_index);
da7e457c
LP
970 if (r < 0) {
971 source_free(s);
972 return r;
973 }
974
975 *ret = s;
976 return 0;
977}
978
f7262a9f 979_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
da7e457c
LP
980 assert_return(s, NULL);
981
982 assert(s->n_ref >= 1);
983 s->n_ref++;
fd38203a
LP
984
985 return s;
986}
987
f7262a9f 988_public_ sd_event_source* sd_event_source_unref(sd_event_source *s) {
5b1bc83f
LP
989
990 if (!s)
991 return NULL;
fd38203a 992
da7e457c
LP
993 assert(s->n_ref >= 1);
994 s->n_ref--;
995
996 if (s->n_ref <= 0)
fd38203a
LP
997 source_free(s);
998
999 return NULL;
1000}
1001
adcc4ca3 1002_public_ sd_event *sd_event_source_get_event(sd_event_source *s) {
305f78bf 1003 assert_return(s, NULL);
eaa3cbef
LP
1004
1005 return s->event;
1006}
1007
f7262a9f 1008_public_ int sd_event_source_get_pending(sd_event_source *s) {
305f78bf 1009 assert_return(s, -EINVAL);
6203e07a 1010 assert_return(s->type != SOURCE_EXIT, -EDOM);
da7e457c 1011 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1012 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1013
1014 return s->pending;
1015}
1016
f7262a9f 1017_public_ int sd_event_source_get_io_fd(sd_event_source *s) {
305f78bf
LP
1018 assert_return(s, -EINVAL);
1019 assert_return(s->type == SOURCE_IO, -EDOM);
1020 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1021
1022 return s->io.fd;
1023}
1024
f7262a9f 1025_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) {
305f78bf
LP
1026 assert_return(s, -EINVAL);
1027 assert_return(events, -EINVAL);
1028 assert_return(s->type == SOURCE_IO, -EDOM);
1029 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1030
1031 *events = s->io.events;
1032 return 0;
1033}
1034
f7262a9f 1035_public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) {
fd38203a
LP
1036 int r;
1037
305f78bf
LP
1038 assert_return(s, -EINVAL);
1039 assert_return(s->type == SOURCE_IO, -EDOM);
2a16a986 1040 assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
da7e457c 1041 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1042 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1043
1044 if (s->io.events == events)
1045 return 0;
1046
baf76283 1047 if (s->enabled != SD_EVENT_OFF) {
e4715127 1048 r = source_io_register(s, s->enabled, events);
fd38203a
LP
1049 if (r < 0)
1050 return r;
1051 }
1052
1053 s->io.events = events;
503f39c3 1054 source_set_pending(s, false);
fd38203a
LP
1055
1056 return 0;
1057}
1058
f7262a9f 1059_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) {
305f78bf
LP
1060 assert_return(s, -EINVAL);
1061 assert_return(revents, -EINVAL);
1062 assert_return(s->type == SOURCE_IO, -EDOM);
1063 assert_return(s->pending, -ENODATA);
1064 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1065
1066 *revents = s->io.revents;
1067 return 0;
1068}
1069
f7262a9f 1070_public_ int sd_event_source_get_signal(sd_event_source *s) {
305f78bf
LP
1071 assert_return(s, -EINVAL);
1072 assert_return(s->type == SOURCE_SIGNAL, -EDOM);
1073 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1074
1075 return s->signal.sig;
1076}
1077
f7262a9f 1078_public_ int sd_event_source_get_priority(sd_event_source *s, int *priority) {
305f78bf
LP
1079 assert_return(s, -EINVAL);
1080 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1081
1082 return s->priority;
1083}
1084
f7262a9f 1085_public_ int sd_event_source_set_priority(sd_event_source *s, int priority) {
305f78bf 1086 assert_return(s, -EINVAL);
da7e457c 1087 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1088 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1089
1090 if (s->priority == priority)
1091 return 0;
1092
1093 s->priority = priority;
1094
1095 if (s->pending)
c2ba3ad6 1096 prioq_reshuffle(s->event->pending, s, &s->pending_index);
fd38203a
LP
1097
1098 if (s->prepare)
c2ba3ad6 1099 prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
fd38203a 1100
6203e07a
LP
1101 if (s->type == SOURCE_EXIT)
1102 prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
305f78bf 1103
fd38203a
LP
1104 return 0;
1105}
1106
f7262a9f 1107_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
305f78bf
LP
1108 assert_return(s, -EINVAL);
1109 assert_return(m, -EINVAL);
1110 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1111
baf76283 1112 *m = s->enabled;
fd38203a
LP
1113 return 0;
1114}
1115
f7262a9f 1116_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
fd38203a
LP
1117 int r;
1118
305f78bf
LP
1119 assert_return(s, -EINVAL);
1120 assert_return(m == SD_EVENT_OFF || m == SD_EVENT_ON || m == SD_EVENT_ONESHOT, -EINVAL);
da7e457c 1121 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1122 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1123
baf76283 1124 if (s->enabled == m)
fd38203a
LP
1125 return 0;
1126
baf76283 1127 if (m == SD_EVENT_OFF) {
fd38203a
LP
1128
1129 switch (s->type) {
1130
1131 case SOURCE_IO:
1132 r = source_io_unregister(s);
1133 if (r < 0)
1134 return r;
1135
baf76283 1136 s->enabled = m;
fd38203a
LP
1137 break;
1138
1139 case SOURCE_MONOTONIC:
baf76283 1140 s->enabled = m;
c2ba3ad6
LP
1141 prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
1142 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
fd38203a
LP
1143 break;
1144
1145 case SOURCE_REALTIME:
baf76283 1146 s->enabled = m;
c2ba3ad6
LP
1147 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
1148 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
fd38203a
LP
1149 break;
1150
1151 case SOURCE_SIGNAL:
baf76283
LP
1152 s->enabled = m;
1153 if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0) {
fd38203a
LP
1154 assert_se(sigdelset(&s->event->sigset, s->signal.sig) == 0);
1155 event_update_signal_fd(s->event);
1156 }
1157
1158 break;
1159
1160 case SOURCE_CHILD:
baf76283 1161 s->enabled = m;
fd38203a 1162
baf76283
LP
1163 assert(s->event->n_enabled_child_sources > 0);
1164 s->event->n_enabled_child_sources--;
fd38203a
LP
1165
1166 if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) {
1167 assert_se(sigdelset(&s->event->sigset, SIGCHLD) == 0);
1168 event_update_signal_fd(s->event);
1169 }
1170
1171 break;
1172
6203e07a 1173 case SOURCE_EXIT:
305f78bf 1174 s->enabled = m;
6203e07a 1175 prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
305f78bf
LP
1176 break;
1177
1178 case SOURCE_DEFER:
baf76283 1179 s->enabled = m;
fd38203a
LP
1180 break;
1181 }
1182
1183 } else {
1184 switch (s->type) {
1185
1186 case SOURCE_IO:
1187 r = source_io_register(s, m, s->io.events);
1188 if (r < 0)
1189 return r;
1190
baf76283 1191 s->enabled = m;
fd38203a
LP
1192 break;
1193
1194 case SOURCE_MONOTONIC:
baf76283 1195 s->enabled = m;
c2ba3ad6
LP
1196 prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
1197 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
fd38203a
LP
1198 break;
1199
1200 case SOURCE_REALTIME:
baf76283 1201 s->enabled = m;
c2ba3ad6
LP
1202 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
1203 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
fd38203a
LP
1204 break;
1205
1206 case SOURCE_SIGNAL:
baf76283 1207 s->enabled = m;
fd38203a 1208
baf76283 1209 if (s->signal.sig != SIGCHLD || s->event->n_enabled_child_sources == 0) {
fd38203a
LP
1210 assert_se(sigaddset(&s->event->sigset, s->signal.sig) == 0);
1211 event_update_signal_fd(s->event);
1212 }
1213 break;
1214
1215 case SOURCE_CHILD:
baf76283 1216 s->enabled = m;
fd38203a 1217
baf76283
LP
1218 if (s->enabled == SD_EVENT_OFF) {
1219 s->event->n_enabled_child_sources++;
fd38203a
LP
1220
1221 if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) {
1222 assert_se(sigaddset(&s->event->sigset, SIGCHLD) == 0);
1223 event_update_signal_fd(s->event);
1224 }
1225 }
1226 break;
1227
6203e07a 1228 case SOURCE_EXIT:
305f78bf 1229 s->enabled = m;
6203e07a 1230 prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
305f78bf
LP
1231 break;
1232
1233 case SOURCE_DEFER:
baf76283 1234 s->enabled = m;
fd38203a
LP
1235 break;
1236 }
1237 }
1238
1239 if (s->pending)
1240 prioq_reshuffle(s->event->pending, s, &s->pending_index);
1241
1242 if (s->prepare)
1243 prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
1244
1245 return 0;
1246}
1247
f7262a9f 1248_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
305f78bf
LP
1249 assert_return(s, -EINVAL);
1250 assert_return(usec, -EINVAL);
1251 assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
1252 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1253
1254 *usec = s->time.next;
1255 return 0;
1256}
1257
f7262a9f 1258_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
305f78bf
LP
1259 assert_return(s, -EINVAL);
1260 assert_return(usec != (uint64_t) -1, -EINVAL);
1261 assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
da7e457c 1262 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1263 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a 1264
fd38203a 1265 s->time.next = usec;
2576a19e 1266
0cc1125a 1267 source_set_pending(s, false);
fd38203a 1268
c2ba3ad6
LP
1269 if (s->type == SOURCE_REALTIME) {
1270 prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
1271 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
1272 } else {
1273 prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
1274 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
1275 }
fd38203a
LP
1276
1277 return 0;
1278}
1279
f7262a9f 1280_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
305f78bf
LP
1281 assert_return(s, -EINVAL);
1282 assert_return(usec, -EINVAL);
1283 assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
1284 assert_return(!event_pid_changed(s->event), -ECHILD);
1285
1286 *usec = s->time.accuracy;
1287 return 0;
1288}
1289
f7262a9f 1290_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
305f78bf
LP
1291 assert_return(s, -EINVAL);
1292 assert_return(usec != (uint64_t) -1, -EINVAL);
1293 assert_return(s->type == SOURCE_REALTIME || s->type == SOURCE_MONOTONIC, -EDOM);
da7e457c 1294 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
305f78bf 1295 assert_return(!event_pid_changed(s->event), -ECHILD);
eaa3cbef
LP
1296
1297 if (usec == 0)
1298 usec = DEFAULT_ACCURACY_USEC;
1299
eaa3cbef
LP
1300 s->time.accuracy = usec;
1301
2576a19e
LP
1302 source_set_pending(s, false);
1303
eaa3cbef
LP
1304 if (s->type == SOURCE_REALTIME)
1305 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
1306 else
1307 prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
1308
1309 return 0;
1310}
1311
f7262a9f 1312_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
4bee8012
LP
1313 assert_return(s, -EINVAL);
1314 assert_return(pid, -EINVAL);
1315 assert_return(s->type == SOURCE_CHILD, -EDOM);
1316 assert_return(!event_pid_changed(s->event), -ECHILD);
1317
1318 *pid = s->child.pid;
1319 return 0;
1320}
1321
718db961 1322_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
fd38203a
LP
1323 int r;
1324
da7e457c 1325 assert_return(s, -EINVAL);
6203e07a 1326 assert_return(s->type != SOURCE_EXIT, -EDOM);
da7e457c
LP
1327 assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
1328 assert_return(!event_pid_changed(s->event), -ECHILD);
fd38203a
LP
1329
1330 if (s->prepare == callback)
1331 return 0;
1332
1333 if (callback && s->prepare) {
1334 s->prepare = callback;
1335 return 0;
1336 }
1337
1338 r = prioq_ensure_allocated(&s->event->prepare, prepare_prioq_compare);
1339 if (r < 0)
1340 return r;
1341
1342 s->prepare = callback;
1343
1344 if (callback) {
1345 r = prioq_put(s->event->prepare, s, &s->prepare_index);
1346 if (r < 0)
1347 return r;
1348 } else
1349 prioq_remove(s->event->prepare, s, &s->prepare_index);
1350
1351 return 0;
1352}
1353
f7262a9f 1354_public_ void* sd_event_source_get_userdata(sd_event_source *s) {
da7e457c 1355 assert_return(s, NULL);
fd38203a
LP
1356
1357 return s->userdata;
1358}
1359
c2ba3ad6
LP
1360static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) {
1361 usec_t c;
1362 assert(e);
1363 assert(a <= b);
1364
1365 if (a <= 0)
1366 return 0;
1367
1368 if (b <= a + 1)
1369 return a;
1370
1371 /*
1372 Find a good time to wake up again between times a and b. We
1373 have two goals here:
1374
1375 a) We want to wake up as seldom as possible, hence prefer
1376 later times over earlier times.
1377
1378 b) But if we have to wake up, then let's make sure to
1379 dispatch as much as possible on the entire system.
1380
1381 We implement this by waking up everywhere at the same time
850516e0 1382 within any given minute if we can, synchronised via the
c2ba3ad6 1383 perturbation value determined from the boot ID. If we can't,
ba276c81
LP
1384 then we try to find the same spot in every 10s, then 1s and
1385 then 250ms step. Otherwise, we pick the last possible time
1386 to wake up.
c2ba3ad6
LP
1387 */
1388
850516e0
LP
1389 c = (b / USEC_PER_MINUTE) * USEC_PER_MINUTE + e->perturb;
1390 if (c >= b) {
1391 if (_unlikely_(c < USEC_PER_MINUTE))
1392 return b;
1393
1394 c -= USEC_PER_MINUTE;
1395 }
1396
ba276c81
LP
1397 if (c >= a)
1398 return c;
1399
1400 c = (b / (USEC_PER_SEC*10)) * (USEC_PER_SEC*10) + (e->perturb % (USEC_PER_SEC*10));
1401 if (c >= b) {
1402 if (_unlikely_(c < USEC_PER_SEC*10))
1403 return b;
1404
1405 c -= USEC_PER_SEC*10;
1406 }
1407
850516e0
LP
1408 if (c >= a)
1409 return c;
1410
1411 c = (b / USEC_PER_SEC) * USEC_PER_SEC + (e->perturb % USEC_PER_SEC);
c2ba3ad6
LP
1412 if (c >= b) {
1413 if (_unlikely_(c < USEC_PER_SEC))
1414 return b;
1415
1416 c -= USEC_PER_SEC;
1417 }
1418
1419 if (c >= a)
1420 return c;
1421
1422 c = (b / (USEC_PER_MSEC*250)) * (USEC_PER_MSEC*250) + (e->perturb % (USEC_PER_MSEC*250));
1423 if (c >= b) {
1424 if (_unlikely_(c < USEC_PER_MSEC*250))
1425 return b;
1426
1427 c -= USEC_PER_MSEC*250;
1428 }
1429
1430 if (c >= a)
1431 return c;
1432
1433 return b;
1434}
1435
fd38203a
LP
1436static int event_arm_timer(
1437 sd_event *e,
1438 int timer_fd,
c2ba3ad6
LP
1439 Prioq *earliest,
1440 Prioq *latest,
fd38203a
LP
1441 usec_t *next) {
1442
1443 struct itimerspec its = {};
c2ba3ad6
LP
1444 sd_event_source *a, *b;
1445 usec_t t;
fd38203a
LP
1446 int r;
1447
cde93897
LP
1448 assert(e);
1449 assert(next);
fd38203a 1450
c2ba3ad6 1451 a = prioq_peek(earliest);
72aedc1e
LP
1452 if (!a || a->enabled == SD_EVENT_OFF) {
1453
c57b5ca3
LP
1454 if (timer_fd < 0)
1455 return 0;
1456
72aedc1e
LP
1457 if (*next == (usec_t) -1)
1458 return 0;
1459
1460 /* disarm */
1461 r = timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &its, NULL);
1462 if (r < 0)
1463 return r;
1464
1465 *next = (usec_t) -1;
1466
fd38203a 1467 return 0;
72aedc1e 1468 }
fd38203a 1469
c2ba3ad6 1470 b = prioq_peek(latest);
baf76283 1471 assert_se(b && b->enabled != SD_EVENT_OFF);
c2ba3ad6
LP
1472
1473 t = sleep_between(e, a->time.next, b->time.next + b->time.accuracy);
1474 if (*next == t)
fd38203a
LP
1475 return 0;
1476
1477 assert_se(timer_fd >= 0);
1478
c2ba3ad6 1479 if (t == 0) {
fd38203a
LP
1480 /* We don' want to disarm here, just mean some time looooong ago. */
1481 its.it_value.tv_sec = 0;
1482 its.it_value.tv_nsec = 1;
1483 } else
c2ba3ad6 1484 timespec_store(&its.it_value, t);
fd38203a
LP
1485
1486 r = timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &its, NULL);
1487 if (r < 0)
cde93897 1488 return -errno;
fd38203a 1489
c2ba3ad6 1490 *next = t;
fd38203a
LP
1491 return 0;
1492}
1493
1494static int process_io(sd_event *e, sd_event_source *s, uint32_t events) {
1495 assert(e);
1496 assert(s);
1497 assert(s->type == SOURCE_IO);
1498
1499 s->io.revents = events;
1500
fd38203a
LP
1501 return source_set_pending(s, true);
1502}
1503
72aedc1e 1504static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) {
fd38203a
LP
1505 uint64_t x;
1506 ssize_t ss;
1507
1508 assert(e);
da7e457c 1509 assert(fd >= 0);
72aedc1e 1510
305f78bf 1511 assert_return(events == EPOLLIN, -EIO);
fd38203a
LP
1512
1513 ss = read(fd, &x, sizeof(x));
1514 if (ss < 0) {
1515 if (errno == EAGAIN || errno == EINTR)
1516 return 0;
1517
1518 return -errno;
1519 }
1520
1521 if (ss != sizeof(x))
1522 return -EIO;
1523
cde93897
LP
1524 if (next)
1525 *next = (usec_t) -1;
72aedc1e 1526
fd38203a
LP
1527 return 0;
1528}
1529
305f78bf
LP
1530static int process_timer(
1531 sd_event *e,
1532 usec_t n,
1533 Prioq *earliest,
1534 Prioq *latest) {
1535
fd38203a
LP
1536 sd_event_source *s;
1537 int r;
1538
1539 assert(e);
1540
1541 for (;;) {
c2ba3ad6 1542 s = prioq_peek(earliest);
fd38203a
LP
1543 if (!s ||
1544 s->time.next > n ||
baf76283 1545 s->enabled == SD_EVENT_OFF ||
fd38203a
LP
1546 s->pending)
1547 break;
1548
1549 r = source_set_pending(s, true);
1550 if (r < 0)
1551 return r;
1552
c2ba3ad6
LP
1553 prioq_reshuffle(earliest, s, &s->time.earliest_index);
1554 prioq_reshuffle(latest, s, &s->time.latest_index);
fd38203a
LP
1555 }
1556
1557 return 0;
1558}
1559
1560static int process_child(sd_event *e) {
1561 sd_event_source *s;
1562 Iterator i;
1563 int r;
1564
1565 assert(e);
1566
c2ba3ad6
LP
1567 e->need_process_child = false;
1568
fd38203a
LP
1569 /*
1570 So, this is ugly. We iteratively invoke waitid() with P_PID
1571 + WNOHANG for each PID we wait for, instead of using
1572 P_ALL. This is because we only want to get child
1573 information of very specific child processes, and not all
1574 of them. We might not have processed the SIGCHLD even of a
1575 previous invocation and we don't want to maintain a
1576 unbounded *per-child* event queue, hence we really don't
1577 want anything flushed out of the kernel's queue that we
1578 don't care about. Since this is O(n) this means that if you
1579 have a lot of processes you probably want to handle SIGCHLD
1580 yourself.
08cd1552
LP
1581
1582 We do not reap the children here (by using WNOWAIT), this
1583 is only done after the event source is dispatched so that
1584 the callback still sees the process as a zombie.
fd38203a
LP
1585 */
1586
1587 HASHMAP_FOREACH(s, e->child_sources, i) {
1588 assert(s->type == SOURCE_CHILD);
1589
1590 if (s->pending)
1591 continue;
1592
baf76283 1593 if (s->enabled == SD_EVENT_OFF)
fd38203a
LP
1594 continue;
1595
1596 zero(s->child.siginfo);
08cd1552
LP
1597 r = waitid(P_PID, s->child.pid, &s->child.siginfo,
1598 WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options);
fd38203a
LP
1599 if (r < 0)
1600 return -errno;
1601
1602 if (s->child.siginfo.si_pid != 0) {
08cd1552
LP
1603 bool zombie =
1604 s->child.siginfo.si_code == CLD_EXITED ||
1605 s->child.siginfo.si_code == CLD_KILLED ||
1606 s->child.siginfo.si_code == CLD_DUMPED;
1607
1608 if (!zombie && (s->child.options & WEXITED)) {
1609 /* If the child isn't dead then let's
1610 * immediately remove the state change
1611 * from the queue, since there's no
1612 * benefit in leaving it queued */
1613
1614 assert(s->child.options & (WSTOPPED|WCONTINUED));
1615 waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED)));
1616 }
1617
fd38203a
LP
1618 r = source_set_pending(s, true);
1619 if (r < 0)
1620 return r;
1621 }
1622 }
1623
fd38203a
LP
1624 return 0;
1625}
1626
1627static int process_signal(sd_event *e, uint32_t events) {
fd38203a 1628 bool read_one = false;
fd38203a
LP
1629 int r;
1630
da7e457c 1631 assert(e);
0eb2e0e3
ZJS
1632 assert(e->signal_sources);
1633
305f78bf 1634 assert_return(events == EPOLLIN, -EIO);
fd38203a
LP
1635
1636 for (;;) {
0eb2e0e3
ZJS
1637 struct signalfd_siginfo si;
1638 ssize_t ss;
fd38203a
LP
1639 sd_event_source *s;
1640
1641 ss = read(e->signal_fd, &si, sizeof(si));
1642 if (ss < 0) {
1643 if (errno == EAGAIN || errno == EINTR)
1644 return read_one;
1645
1646 return -errno;
1647 }
1648
1649 if (ss != sizeof(si))
1650 return -EIO;
1651
1652 read_one = true;
1653
0eb2e0e3 1654 s = e->signal_sources[si.ssi_signo];
fd38203a
LP
1655 if (si.ssi_signo == SIGCHLD) {
1656 r = process_child(e);
1657 if (r < 0)
1658 return r;
0eb2e0e3 1659 if (r > 0 || !s)
fd38203a 1660 continue;
0eb2e0e3 1661 } else
fd38203a
LP
1662 if (!s)
1663 return -EIO;
fd38203a
LP
1664
1665 s->signal.siginfo = si;
1666 r = source_set_pending(s, true);
1667 if (r < 0)
1668 return r;
1669 }
1670
fd38203a
LP
1671 return 0;
1672}
1673
1674static int source_dispatch(sd_event_source *s) {
fe8245eb 1675 int r = 0;
fd38203a
LP
1676
1677 assert(s);
6203e07a 1678 assert(s->pending || s->type == SOURCE_EXIT);
fd38203a 1679
6203e07a 1680 if (s->type != SOURCE_DEFER && s->type != SOURCE_EXIT) {
da7e457c
LP
1681 r = source_set_pending(s, false);
1682 if (r < 0)
1683 return r;
1684 }
fd38203a 1685
baf76283
LP
1686 if (s->enabled == SD_EVENT_ONESHOT) {
1687 r = sd_event_source_set_enabled(s, SD_EVENT_OFF);
fd38203a
LP
1688 if (r < 0)
1689 return r;
1690 }
1691
b7484e2a
LP
1692 sd_event_source_ref(s);
1693
fd38203a
LP
1694 switch (s->type) {
1695
1696 case SOURCE_IO:
1697 r = s->io.callback(s, s->io.fd, s->io.revents, s->userdata);
1698 break;
1699
1700 case SOURCE_MONOTONIC:
1701 r = s->time.callback(s, s->time.next, s->userdata);
1702 break;
1703
1704 case SOURCE_REALTIME:
1705 r = s->time.callback(s, s->time.next, s->userdata);
1706 break;
1707
1708 case SOURCE_SIGNAL:
1709 r = s->signal.callback(s, &s->signal.siginfo, s->userdata);
1710 break;
1711
08cd1552
LP
1712 case SOURCE_CHILD: {
1713 bool zombie;
1714
1715 zombie = s->child.siginfo.si_code == CLD_EXITED ||
1716 s->child.siginfo.si_code == CLD_KILLED ||
1717 s->child.siginfo.si_code == CLD_DUMPED;
1718
fd38203a 1719 r = s->child.callback(s, &s->child.siginfo, s->userdata);
08cd1552
LP
1720
1721 /* Now, reap the PID for good. */
1722 if (zombie)
1723 waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
1724
fd38203a 1725 break;
08cd1552 1726 }
fd38203a
LP
1727
1728 case SOURCE_DEFER:
1729 r = s->defer.callback(s, s->userdata);
1730 break;
da7e457c 1731
6203e07a
LP
1732 case SOURCE_EXIT:
1733 r = s->exit.callback(s, s->userdata);
da7e457c 1734 break;
fd38203a
LP
1735 }
1736
6203e07a
LP
1737 if (r < 0) {
1738 log_debug("Event source %p returned error, disabling: %s", s, strerror(-r));
1739 sd_event_source_set_enabled(s, SD_EVENT_OFF);
1740 }
b7484e2a 1741
6203e07a
LP
1742 sd_event_source_unref(s);
1743 return 1;
fd38203a
LP
1744}
1745
1746static int event_prepare(sd_event *e) {
1747 int r;
1748
1749 assert(e);
1750
1751 for (;;) {
1752 sd_event_source *s;
1753
1754 s = prioq_peek(e->prepare);
baf76283 1755 if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF)
fd38203a
LP
1756 break;
1757
1758 s->prepare_iteration = e->iteration;
1759 r = prioq_reshuffle(e->prepare, s, &s->prepare_index);
1760 if (r < 0)
1761 return r;
1762
1763 assert(s->prepare);
1764 r = s->prepare(s, s->userdata);
1765 if (r < 0)
1766 return r;
1767
1768 }
1769
1770 return 0;
1771}
1772
6203e07a 1773static int dispatch_exit(sd_event *e) {
da7e457c
LP
1774 sd_event_source *p;
1775 int r;
1776
1777 assert(e);
1778
6203e07a 1779 p = prioq_peek(e->exit);
baf76283 1780 if (!p || p->enabled == SD_EVENT_OFF) {
da7e457c
LP
1781 e->state = SD_EVENT_FINISHED;
1782 return 0;
1783 }
1784
1785 sd_event_ref(e);
1786 e->iteration++;
6203e07a 1787 e->state = SD_EVENT_EXITING;
da7e457c
LP
1788
1789 r = source_dispatch(p);
1790
1791 e->state = SD_EVENT_PASSIVE;
1792 sd_event_unref(e);
1793
1794 return r;
1795}
1796
c2ba3ad6
LP
1797static sd_event_source* event_next_pending(sd_event *e) {
1798 sd_event_source *p;
1799
da7e457c
LP
1800 assert(e);
1801
c2ba3ad6
LP
1802 p = prioq_peek(e->pending);
1803 if (!p)
1804 return NULL;
1805
baf76283 1806 if (p->enabled == SD_EVENT_OFF)
c2ba3ad6
LP
1807 return NULL;
1808
1809 return p;
1810}
1811
cde93897
LP
1812static int arm_watchdog(sd_event *e) {
1813 struct itimerspec its = {};
1814 usec_t t;
1815 int r;
1816
1817 assert(e);
1818 assert(e->watchdog_fd >= 0);
1819
1820 t = sleep_between(e,
1821 e->watchdog_last + (e->watchdog_period / 2),
1822 e->watchdog_last + (e->watchdog_period * 3 / 4));
1823
1824 timespec_store(&its.it_value, t);
1825
1826 r = timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL);
1827 if (r < 0)
1828 return -errno;
1829
1830 return 0;
1831}
1832
1833static int process_watchdog(sd_event *e) {
1834 assert(e);
1835
1836 if (!e->watchdog)
1837 return 0;
1838
1839 /* Don't notify watchdog too often */
1840 if (e->watchdog_last + e->watchdog_period / 4 > e->timestamp.monotonic)
1841 return 0;
1842
1843 sd_notify(false, "WATCHDOG=1");
1844 e->watchdog_last = e->timestamp.monotonic;
1845
1846 return arm_watchdog(e);
1847}
1848
f7262a9f 1849_public_ int sd_event_run(sd_event *e, uint64_t timeout) {
fd38203a
LP
1850 struct epoll_event ev_queue[EPOLL_QUEUE_MAX];
1851 sd_event_source *p;
305f78bf 1852 int r, i, m;
fd38203a 1853
da7e457c
LP
1854 assert_return(e, -EINVAL);
1855 assert_return(!event_pid_changed(e), -ECHILD);
1856 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
1857 assert_return(e->state == SD_EVENT_PASSIVE, -EBUSY);
1858
6203e07a
LP
1859 if (e->exit_requested)
1860 return dispatch_exit(e);
fd38203a 1861
da7e457c 1862 sd_event_ref(e);
fd38203a 1863 e->iteration++;
da7e457c 1864 e->state = SD_EVENT_RUNNING;
fd38203a
LP
1865
1866 r = event_prepare(e);
1867 if (r < 0)
da7e457c 1868 goto finish;
fd38203a 1869
1b5995b0
LP
1870 r = event_arm_timer(e, e->monotonic_fd, e->monotonic_earliest, e->monotonic_latest, &e->monotonic_next);
1871 if (r < 0)
1872 goto finish;
fd38203a 1873
1b5995b0
LP
1874 r = event_arm_timer(e, e->realtime_fd, e->realtime_earliest, e->realtime_latest, &e->realtime_next);
1875 if (r < 0)
1876 goto finish;
fd38203a 1877
1b5995b0
LP
1878 if (event_next_pending(e) || e->need_process_child)
1879 timeout = 0;
fd38203a 1880
c2ba3ad6
LP
1881 m = epoll_wait(e->epoll_fd, ev_queue, EPOLL_QUEUE_MAX,
1882 timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
da7e457c 1883 if (m < 0) {
d09d5ecd 1884 r = errno == EAGAIN || errno == EINTR ? 0 : -errno;
da7e457c
LP
1885 goto finish;
1886 }
fd38203a 1887
46e8c825 1888 dual_timestamp_get(&e->timestamp);
fd38203a
LP
1889
1890 for (i = 0; i < m; i++) {
1891
1892 if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_MONOTONIC))
72aedc1e 1893 r = flush_timer(e, e->monotonic_fd, ev_queue[i].events, &e->monotonic_next);
fd38203a 1894 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_REALTIME))
72aedc1e 1895 r = flush_timer(e, e->realtime_fd, ev_queue[i].events, &e->realtime_next);
fd38203a
LP
1896 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_SIGNAL))
1897 r = process_signal(e, ev_queue[i].events);
cde93897
LP
1898 else if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG))
1899 r = flush_timer(e, e->watchdog_fd, ev_queue[i].events, NULL);
fd38203a
LP
1900 else
1901 r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events);
1902
1903 if (r < 0)
da7e457c 1904 goto finish;
fd38203a
LP
1905 }
1906
cde93897
LP
1907 r = process_watchdog(e);
1908 if (r < 0)
1909 goto finish;
1910
46e8c825 1911 r = process_timer(e, e->timestamp.monotonic, e->monotonic_earliest, e->monotonic_latest);
fd38203a 1912 if (r < 0)
da7e457c 1913 goto finish;
fd38203a 1914
46e8c825 1915 r = process_timer(e, e->timestamp.realtime, e->realtime_earliest, e->realtime_latest);
fd38203a 1916 if (r < 0)
da7e457c 1917 goto finish;
fd38203a 1918
c2ba3ad6 1919 if (e->need_process_child) {
fd38203a
LP
1920 r = process_child(e);
1921 if (r < 0)
da7e457c 1922 goto finish;
fd38203a
LP
1923 }
1924
c2ba3ad6 1925 p = event_next_pending(e);
da7e457c
LP
1926 if (!p) {
1927 r = 0;
1928 goto finish;
1929 }
1930
1931 r = source_dispatch(p);
fd38203a 1932
da7e457c
LP
1933finish:
1934 e->state = SD_EVENT_PASSIVE;
1935 sd_event_unref(e);
1936
1937 return r;
fd38203a
LP
1938}
1939
f7262a9f 1940_public_ int sd_event_loop(sd_event *e) {
fd38203a
LP
1941 int r;
1942
da7e457c
LP
1943 assert_return(e, -EINVAL);
1944 assert_return(!event_pid_changed(e), -ECHILD);
1945 assert_return(e->state == SD_EVENT_PASSIVE, -EBUSY);
1946
1947 sd_event_ref(e);
fd38203a 1948
da7e457c 1949 while (e->state != SD_EVENT_FINISHED) {
fd38203a
LP
1950 r = sd_event_run(e, (uint64_t) -1);
1951 if (r < 0)
da7e457c 1952 goto finish;
fd38203a
LP
1953 }
1954
6203e07a 1955 r = e->exit_code;
da7e457c
LP
1956
1957finish:
1958 sd_event_unref(e);
1959 return r;
fd38203a
LP
1960}
1961
f7262a9f 1962_public_ int sd_event_get_state(sd_event *e) {
da7e457c
LP
1963 assert_return(e, -EINVAL);
1964 assert_return(!event_pid_changed(e), -ECHILD);
1965
1966 return e->state;
1967}
1968
6203e07a 1969_public_ int sd_event_get_exit_code(sd_event *e, int *code) {
da7e457c 1970 assert_return(e, -EINVAL);
6203e07a 1971 assert_return(code, -EINVAL);
da7e457c 1972 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 1973
6203e07a
LP
1974 if (!e->exit_requested)
1975 return -ENODATA;
1976
1977 *code = e->exit_code;
1978 return 0;
fd38203a
LP
1979}
1980
6203e07a 1981_public_ int sd_event_exit(sd_event *e, int code) {
da7e457c
LP
1982 assert_return(e, -EINVAL);
1983 assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
1984 assert_return(!event_pid_changed(e), -ECHILD);
fd38203a 1985
6203e07a
LP
1986 e->exit_requested = true;
1987 e->exit_code = code;
1988
fd38203a
LP
1989 return 0;
1990}
46e8c825 1991
f7262a9f 1992_public_ int sd_event_get_now_realtime(sd_event *e, uint64_t *usec) {
46e8c825
LP
1993 assert_return(e, -EINVAL);
1994 assert_return(usec, -EINVAL);
1995 assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA);
1996 assert_return(!event_pid_changed(e), -ECHILD);
1997
1998 *usec = e->timestamp.realtime;
1999 return 0;
2000}
2001
f7262a9f 2002_public_ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) {
46e8c825
LP
2003 assert_return(e, -EINVAL);
2004 assert_return(usec, -EINVAL);
2005 assert_return(dual_timestamp_is_set(&e->timestamp), -ENODATA);
2006 assert_return(!event_pid_changed(e), -ECHILD);
2007
2008 *usec = e->timestamp.monotonic;
2009 return 0;
2010}
afc6adb5
LP
2011
2012_public_ int sd_event_default(sd_event **ret) {
2013
2014 static __thread sd_event *default_event = NULL;
2015 sd_event *e;
2016 int r;
2017
2018 if (!ret)
2019 return !!default_event;
2020
2021 if (default_event) {
2022 *ret = sd_event_ref(default_event);
2023 return 0;
2024 }
2025
2026 r = sd_event_new(&e);
2027 if (r < 0)
2028 return r;
2029
2030 e->default_event_ptr = &default_event;
2031 e->tid = gettid();
2032 default_event = e;
2033
2034 *ret = e;
2035 return 1;
2036}
2037
2038_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) {
2039 assert_return(e, -EINVAL);
2040 assert_return(tid, -EINVAL);
76b54375 2041 assert_return(!event_pid_changed(e), -ECHILD);
afc6adb5 2042
76b54375
LP
2043 if (e->tid != 0) {
2044 *tid = e->tid;
2045 return 0;
2046 }
2047
2048 return -ENXIO;
afc6adb5 2049}
cde93897
LP
2050
2051_public_ int sd_event_set_watchdog(sd_event *e, int b) {
2052 int r;
2053
2054 assert_return(e, -EINVAL);
2055
2056 if (e->watchdog == !!b)
2057 return e->watchdog;
2058
2059 if (b) {
2060 struct epoll_event ev = {};
2061 const char *env;
2062
2063 env = getenv("WATCHDOG_USEC");
2064 if (!env)
2065 return false;
2066
2067 r = safe_atou64(env, &e->watchdog_period);
2068 if (r < 0)
2069 return r;
2070 if (e->watchdog_period <= 0)
2071 return -EIO;
2072
2073 /* Issue first ping immediately */
2074 sd_notify(false, "WATCHDOG=1");
2075 e->watchdog_last = now(CLOCK_MONOTONIC);
2076
2077 e->watchdog_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
2078 if (e->watchdog_fd < 0)
2079 return -errno;
2080
2081 r = arm_watchdog(e);
2082 if (r < 0)
2083 goto fail;
2084
2085 ev.events = EPOLLIN;
2086 ev.data.ptr = INT_TO_PTR(SOURCE_WATCHDOG);
2087
2088 r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev);
2089 if (r < 0) {
2090 r = -errno;
2091 goto fail;
2092 }
2093
2094 } else {
2095 if (e->watchdog_fd >= 0) {
2096 epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, e->watchdog_fd, NULL);
2097 close_nointr_nofail(e->watchdog_fd);
2098 e->watchdog_fd = -1;
2099 }
2100 }
2101
2102 e->watchdog = !!b;
2103 return e->watchdog;
2104
2105fail:
2106 close_nointr_nofail(e->watchdog_fd);
2107 e->watchdog_fd = -1;
2108 return r;
2109}