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