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