1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
26 #include "signal-util.h"
28 static int prepare_handler(sd_event_source *s, void *userdata) {
29 log_info("preparing %c", PTR_TO_INT(userdata));
33 static bool got_a, got_b, got_c, got_unref;
34 static unsigned got_d;
36 static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
37 sd_event_source_unref(s);
42 static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
44 log_info("got IO on %c", PTR_TO_INT(userdata));
46 if (userdata == INT_TO_PTR('a')) {
47 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
50 } else if (userdata == INT_TO_PTR('b')) {
53 } else if (userdata == INT_TO_PTR('d')) {
56 assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0);
58 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
60 assert_not_reached("Yuck!");
65 static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
70 log_info("got child on %c", PTR_TO_INT(userdata));
72 assert_se(userdata == INT_TO_PTR('f'));
74 assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
75 sd_event_source_unref(s);
80 static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
81 sd_event_source *p = NULL;
88 log_info("got signal on %c", PTR_TO_INT(userdata));
90 assert_se(userdata == INT_TO_PTR('e'));
92 assert_se(sigemptyset(&ss) >= 0);
93 assert_se(sigaddset(&ss, SIGCHLD) >= 0);
94 assert_se(sigprocmask(SIG_BLOCK, &ss, NULL) >= 0);
102 assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
103 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
105 sd_event_source_unref(s);
110 static int defer_handler(sd_event_source *s, void *userdata) {
111 sd_event_source *p = NULL;
116 log_info("got defer on %c", PTR_TO_INT(userdata));
118 assert_se(userdata == INT_TO_PTR('d'));
120 assert_se(sigemptyset(&ss) >= 0);
121 assert_se(sigaddset(&ss, SIGUSR1) >= 0);
122 assert_se(sigprocmask(SIG_BLOCK, &ss, NULL) >= 0);
123 assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
124 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
127 sd_event_source_unref(s);
132 static bool do_quit = false;
134 static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
135 log_info("got timer on %c", PTR_TO_INT(userdata));
137 if (userdata == INT_TO_PTR('c')) {
142 assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0);
143 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
149 assert_not_reached("Huh?");
154 static bool got_exit = false;
156 static int exit_handler(sd_event_source *s, void *userdata) {
157 log_info("got quit handler on %c", PTR_TO_INT(userdata));
164 int main(int argc, char *argv[]) {
166 sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL;
167 static const char ch = 'x';
168 int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 };
170 assert_se(pipe(a) >= 0);
171 assert_se(pipe(b) >= 0);
172 assert_se(pipe(d) >= 0);
173 assert_se(pipe(k) >= 0);
175 assert_se(sd_event_default(&e) >= 0);
177 assert_se(sd_event_set_watchdog(e, true) >= 0);
179 /* Test whether we cleanly can destroy an io event source from its own handler */
181 assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0);
182 assert_se(write(k[1], &ch, 1) == 1);
183 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
184 assert_se(got_unref);
186 got_a = false, got_b = false, got_c = false, got_d = 0;
188 /* Add a oneshot handler, trigger it, re-enable it, and trigger
190 assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
191 assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
192 assert_se(write(d[1], &ch, 1) >= 0);
193 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
194 assert_se(got_d == 1);
195 assert_se(write(d[1], &ch, 1) >= 0);
196 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
197 assert_se(got_d == 2);
199 assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0);
200 assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0);
201 assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0);
202 assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0);
204 assert_se(sd_event_source_set_priority(x, 99) >= 0);
205 assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0);
206 assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0);
207 assert_se(sd_event_source_set_priority(z, 50) >= 0);
208 assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
209 assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
211 /* Test for floating event sources */
212 assert_se(sigprocmask_many(SIG_BLOCK, SIGRTMIN+1, -1) == 0);
213 assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
215 assert_se(write(a[1], &ch, 1) >= 0);
216 assert_se(write(b[1], &ch, 1) >= 0);
218 assert_se(!got_a && !got_b && !got_c);
220 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
222 assert_se(!got_a && got_b && !got_c);
224 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
226 assert_se(!got_a && got_b && got_c);
228 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
230 assert_se(got_a && got_b && got_c);
232 sd_event_source_unref(x);
233 sd_event_source_unref(y);
236 assert_se(sd_event_source_set_time(z, now(CLOCK_MONOTONIC) + 200 * USEC_PER_MSEC) >= 0);
237 assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
239 assert_se(sd_event_loop(e) >= 0);
241 sd_event_source_unref(z);
242 sd_event_source_unref(q);
244 sd_event_source_unref(w);