]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-event/test-event.c
util-lib: split out fd-related operations into fd-util.[ch]
[thirdparty/systemd.git] / src / libsystemd / sd-event / test-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 "sd-event.h"
3ffd4af2
LP
23
24#include "fd-util.h"
fd38203a 25#include "log.h"
0c0cdb06 26#include "macro.h"
24882e06 27#include "signal-util.h"
3ffd4af2 28#include "util.h"
fd38203a
LP
29
30static int prepare_handler(sd_event_source *s, void *userdata) {
31 log_info("preparing %c", PTR_TO_INT(userdata));
32 return 1;
33}
34
12179984 35static bool got_a, got_b, got_c, got_unref;
9ec9694c 36static unsigned got_d;
fd38203a 37
12179984
LP
38static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
39 sd_event_source_unref(s);
40 got_unref = true;
41 return 0;
42}
43
fd38203a
LP
44static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
45
46 log_info("got IO on %c", PTR_TO_INT(userdata));
47
48 if (userdata == INT_TO_PTR('a')) {
baf76283 49 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
fd38203a
LP
50 assert_se(!got_a);
51 got_a = true;
52 } else if (userdata == INT_TO_PTR('b')) {
53 assert_se(!got_b);
54 got_b = true;
9ec9694c
DS
55 } else if (userdata == INT_TO_PTR('d')) {
56 got_d++;
57 if (got_d < 2)
58 assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0);
59 else
60 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
fd38203a
LP
61 } else
62 assert_not_reached("Yuck!");
63
64 return 1;
65}
66
67static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
68
0c0cdb06
RC
69 assert_se(s);
70 assert_se(si);
fd38203a
LP
71
72 log_info("got child on %c", PTR_TO_INT(userdata));
73
0c0cdb06 74 assert_se(userdata == INT_TO_PTR('f'));
fd38203a 75
6203e07a 76 assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
fd38203a
LP
77 sd_event_source_unref(s);
78
79 return 1;
80}
81
82static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
39883f62 83 sd_event_source *p = NULL;
fd38203a
LP
84 pid_t pid;
85
0c0cdb06
RC
86 assert_se(s);
87 assert_se(si);
fd38203a
LP
88
89 log_info("got signal on %c", PTR_TO_INT(userdata));
90
0c0cdb06 91 assert_se(userdata == INT_TO_PTR('e'));
fd38203a 92
72c0a2c2 93 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
fd38203a
LP
94
95 pid = fork();
96 assert_se(pid >= 0);
97
98 if (pid == 0)
99 _exit(0);
100
151b9b96 101 assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
baf76283 102 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
fd38203a
LP
103
104 sd_event_source_unref(s);
105
106 return 1;
107}
108
109static int defer_handler(sd_event_source *s, void *userdata) {
39883f62 110 sd_event_source *p = NULL;
fd38203a 111
0c0cdb06 112 assert_se(s);
fd38203a
LP
113
114 log_info("got defer on %c", PTR_TO_INT(userdata));
115
0c0cdb06 116 assert_se(userdata == INT_TO_PTR('d'));
fd38203a 117
72c0a2c2
LP
118 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0);
119
151b9b96 120 assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
baf76283 121 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
fd38203a
LP
122 raise(SIGUSR1);
123
124 sd_event_source_unref(s);
125
126 return 1;
127}
128
129static bool do_quit = false;
130
131static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
132 log_info("got timer on %c", PTR_TO_INT(userdata));
133
134 if (userdata == INT_TO_PTR('c')) {
135
136 if (do_quit) {
137 sd_event_source *p;
138
151b9b96 139 assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0);
baf76283 140 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
fd38203a 141 } else {
0c0cdb06 142 assert_se(!got_c);
fd38203a
LP
143 got_c = true;
144 }
145 } else
146 assert_not_reached("Huh?");
147
148 return 2;
149}
150
6203e07a 151static bool got_exit = false;
da7e457c 152
6203e07a 153static int exit_handler(sd_event_source *s, void *userdata) {
da7e457c
LP
154 log_info("got quit handler on %c", PTR_TO_INT(userdata));
155
6203e07a 156 got_exit = true;
da7e457c
LP
157
158 return 3;
159}
160
9da4cb2b 161static void test_basic(void) {
fd38203a 162 sd_event *e = NULL;
12179984 163 sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL;
fd38203a 164 static const char ch = 'x';
12179984 165 int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 };
fd38203a
LP
166
167 assert_se(pipe(a) >= 0);
168 assert_se(pipe(b) >= 0);
9ec9694c 169 assert_se(pipe(d) >= 0);
12179984 170 assert_se(pipe(k) >= 0);
fd38203a 171
afc6adb5 172 assert_se(sd_event_default(&e) >= 0);
fd38203a 173
cde93897
LP
174 assert_se(sd_event_set_watchdog(e, true) >= 0);
175
12179984
LP
176 /* Test whether we cleanly can destroy an io event source from its own handler */
177 got_unref = false;
151b9b96 178 assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0);
12179984
LP
179 assert_se(write(k[1], &ch, 1) == 1);
180 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
181 assert_se(got_unref);
182
9ec9694c
DS
183 got_a = false, got_b = false, got_c = false, got_d = 0;
184
185 /* Add a oneshot handler, trigger it, re-enable it, and trigger
186 * it again. */
151b9b96 187 assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
9ec9694c
DS
188 assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
189 assert_se(write(d[1], &ch, 1) >= 0);
190 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
191 assert_se(got_d == 1);
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 == 2);
fd38203a 195
151b9b96
LP
196 assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0);
197 assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0);
6a0f1f6d 198 assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0);
151b9b96 199 assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0);
fd38203a
LP
200
201 assert_se(sd_event_source_set_priority(x, 99) >= 0);
baf76283 202 assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0);
fd38203a
LP
203 assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0);
204 assert_se(sd_event_source_set_priority(z, 50) >= 0);
baf76283 205 assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
fd38203a 206 assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
a71fe8b8
LP
207
208 /* Test for floating event sources */
72c0a2c2 209 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1, -1) >= 0);
a71fe8b8 210 assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
fd38203a
LP
211
212 assert_se(write(a[1], &ch, 1) >= 0);
213 assert_se(write(b[1], &ch, 1) >= 0);
214
215 assert_se(!got_a && !got_b && !got_c);
216
217 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
218
219 assert_se(!got_a && got_b && !got_c);
220
221 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
222
223 assert_se(!got_a && got_b && got_c);
224
225 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
226
227 assert_se(got_a && got_b && got_c);
228
229 sd_event_source_unref(x);
230 sd_event_source_unref(y);
231
232 do_quit = true;
233 assert_se(sd_event_source_set_time(z, now(CLOCK_MONOTONIC) + 200 * USEC_PER_MSEC) >= 0);
baf76283 234 assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
fd38203a
LP
235
236 assert_se(sd_event_loop(e) >= 0);
237
238 sd_event_source_unref(z);
da7e457c 239 sd_event_source_unref(q);
fd38203a 240
d5e4ec5b
LP
241 sd_event_source_unref(w);
242
fd38203a
LP
243 sd_event_unref(e);
244
3d94f76c
LP
245 safe_close_pair(a);
246 safe_close_pair(b);
247 safe_close_pair(d);
248 safe_close_pair(k);
9da4cb2b
LP
249}
250
251static int last_rtqueue_sigval = 0;
252static int n_rtqueue = 0;
253
254static int rtqueue_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
255 last_rtqueue_sigval = si->ssi_int;
256 n_rtqueue ++;
257 return 0;
258}
259
260static void test_rtqueue(void) {
261 sd_event_source *u = NULL, *v = NULL, *s = NULL;
262 sd_event *e = NULL;
263
264 assert_se(sd_event_default(&e) >= 0);
265
266 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0);
267 assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0);
268 assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0);
269 assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0);
270
271 assert_se(sd_event_source_set_priority(v, -10) >= 0);
272
273 assert(sigqueue(getpid(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0);
274 assert(sigqueue(getpid(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0);
275 assert(sigqueue(getpid(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0);
276 assert(sigqueue(getpid(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0);
277 assert(sigqueue(getpid(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0);
278
279 assert_se(n_rtqueue == 0);
280 assert_se(last_rtqueue_sigval == 0);
281
282 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
283 assert_se(n_rtqueue == 1);
284 assert_se(last_rtqueue_sigval == 2); /* first SIGRTMIN+3 */
285
286 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
287 assert_se(n_rtqueue == 2);
288 assert_se(last_rtqueue_sigval == 4); /* second SIGRTMIN+3 */
289
290 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
291 assert_se(n_rtqueue == 3);
292 assert_se(last_rtqueue_sigval == 3); /* first SIGUSR2 */
293
294 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
295 assert_se(n_rtqueue == 4);
296 assert_se(last_rtqueue_sigval == 1); /* SIGRTMIN+2 */
297
298 assert_se(sd_event_run(e, 0) == 0); /* the other SIGUSR2 is dropped, because the first one was still queued */
299 assert_se(n_rtqueue == 4);
300 assert_se(last_rtqueue_sigval == 1);
301
302 sd_event_source_unref(u);
303 sd_event_source_unref(v);
304 sd_event_source_unref(s);
305
306 sd_event_unref(e);
307}
308
309int main(int argc, char *argv[]) {
310
311 test_basic();
312 test_rtqueue();
fd38203a
LP
313
314 return 0;
315}