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