]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-event/test-event.c
tests: check exit handler invocation
[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);
5657c75f 237 assert_se(got_exit);
fd38203a
LP
238
239 sd_event_source_unref(z);
da7e457c 240 sd_event_source_unref(q);
fd38203a 241
d5e4ec5b
LP
242 sd_event_source_unref(w);
243
fd38203a
LP
244 sd_event_unref(e);
245
3d94f76c
LP
246 safe_close_pair(a);
247 safe_close_pair(b);
248 safe_close_pair(d);
249 safe_close_pair(k);
9da4cb2b
LP
250}
251
252static int last_rtqueue_sigval = 0;
253static int n_rtqueue = 0;
254
255static int rtqueue_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
256 last_rtqueue_sigval = si->ssi_int;
257 n_rtqueue ++;
258 return 0;
259}
260
261static void test_rtqueue(void) {
262 sd_event_source *u = NULL, *v = NULL, *s = NULL;
263 sd_event *e = NULL;
264
265 assert_se(sd_event_default(&e) >= 0);
266
267 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0);
268 assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0);
269 assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0);
270 assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0);
271
272 assert_se(sd_event_source_set_priority(v, -10) >= 0);
273
274 assert(sigqueue(getpid(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0);
275 assert(sigqueue(getpid(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0);
276 assert(sigqueue(getpid(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0);
277 assert(sigqueue(getpid(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0);
278 assert(sigqueue(getpid(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0);
279
280 assert_se(n_rtqueue == 0);
281 assert_se(last_rtqueue_sigval == 0);
282
283 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
284 assert_se(n_rtqueue == 1);
285 assert_se(last_rtqueue_sigval == 2); /* first SIGRTMIN+3 */
286
287 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
288 assert_se(n_rtqueue == 2);
289 assert_se(last_rtqueue_sigval == 4); /* second SIGRTMIN+3 */
290
291 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
292 assert_se(n_rtqueue == 3);
293 assert_se(last_rtqueue_sigval == 3); /* first SIGUSR2 */
294
295 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
296 assert_se(n_rtqueue == 4);
297 assert_se(last_rtqueue_sigval == 1); /* SIGRTMIN+2 */
298
299 assert_se(sd_event_run(e, 0) == 0); /* the other SIGUSR2 is dropped, because the first one was still queued */
300 assert_se(n_rtqueue == 4);
301 assert_se(last_rtqueue_sigval == 1);
302
303 sd_event_source_unref(u);
304 sd_event_source_unref(v);
305 sd_event_source_unref(s);
306
307 sd_event_unref(e);
308}
309
310int main(int argc, char *argv[]) {
311
312 test_basic();
313 test_rtqueue();
fd38203a
LP
314
315 return 0;
316}