]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-event/test-event.c
pidfd: properly detect if libc offers pidfd syscalls and make use of them then
[thirdparty/systemd.git] / src / libsystemd / sd-event / test-event.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
fd38203a 2
d6bfc3d8
LP
3#if HAVE_PIDFD_OPEN
4#include <sys/pidfd.h>
5#endif
fe993888 6#include <sys/wait.h>
2eeff0f4 7#include <unistd.h>
fe993888 8
fd38203a 9#include "sd-event.h"
3ffd4af2 10
41e09d62 11#include "alloc-util.h"
45a68ed3 12#include "exec-util.h"
3ffd4af2 13#include "fd-util.h"
41e09d62 14#include "fs-util.h"
fd38203a 15#include "log.h"
0c0cdb06 16#include "macro.h"
3ecb3bdc 17#include "missing_syscall.h"
41e09d62 18#include "parse-util.h"
657ee2d8 19#include "path-util.h"
41e09d62 20#include "process-util.h"
c14e57ba 21#include "random-util.h"
41e09d62 22#include "rm-rf.h"
24882e06 23#include "signal-util.h"
41e09d62
LP
24#include "stdio-util.h"
25#include "string-util.h"
6d7c4033 26#include "tests.h"
e4de7287 27#include "tmpfile-util.h"
fd38203a
LP
28
29static int prepare_handler(sd_event_source *s, void *userdata) {
30 log_info("preparing %c", PTR_TO_INT(userdata));
31 return 1;
32}
33
12179984 34static bool got_a, got_b, got_c, got_unref;
9ec9694c 35static unsigned got_d;
fd38203a 36
12179984
LP
37static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
38 sd_event_source_unref(s);
39 got_unref = true;
40 return 0;
41}
42
fd38203a
LP
43static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
44
45 log_info("got IO on %c", PTR_TO_INT(userdata));
46
47 if (userdata == INT_TO_PTR('a')) {
baf76283 48 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
fd38203a
LP
49 assert_se(!got_a);
50 got_a = true;
51 } else if (userdata == INT_TO_PTR('b')) {
52 assert_se(!got_b);
53 got_b = true;
9ec9694c
DS
54 } else if (userdata == INT_TO_PTR('d')) {
55 got_d++;
56 if (got_d < 2)
57 assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0);
58 else
59 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
fd38203a 60 } else
04499a70 61 assert_not_reached();
fd38203a
LP
62
63 return 1;
64}
65
66static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
67
0c0cdb06
RC
68 assert_se(s);
69 assert_se(si);
fd38203a 70
3ecb3bdc
LP
71 assert_se(si->si_uid == getuid());
72 assert_se(si->si_signo == SIGCHLD);
73 assert_se(si->si_code == CLD_EXITED);
74 assert_se(si->si_status == 78);
75
fd38203a
LP
76 log_info("got child on %c", PTR_TO_INT(userdata));
77
0c0cdb06 78 assert_se(userdata == INT_TO_PTR('f'));
fd38203a 79
6203e07a 80 assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
fd38203a
LP
81 sd_event_source_unref(s);
82
83 return 1;
84}
85
86static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
39883f62 87 sd_event_source *p = NULL;
fd38203a 88 pid_t pid;
3ecb3bdc 89 siginfo_t plain_si;
fd38203a 90
0c0cdb06
RC
91 assert_se(s);
92 assert_se(si);
fd38203a
LP
93
94 log_info("got signal on %c", PTR_TO_INT(userdata));
95
0c0cdb06 96 assert_se(userdata == INT_TO_PTR('e'));
fd38203a 97
db7136ec 98 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGUSR2) >= 0);
fd38203a
LP
99
100 pid = fork();
101 assert_se(pid >= 0);
102
3ecb3bdc
LP
103 if (pid == 0) {
104 sigset_t ss;
105
106 assert_se(sigemptyset(&ss) >= 0);
107 assert_se(sigaddset(&ss, SIGUSR2) >= 0);
108
109 zero(plain_si);
110 assert_se(sigwaitinfo(&ss, &plain_si) >= 0);
111
112 assert_se(plain_si.si_signo == SIGUSR2);
113 assert_se(plain_si.si_value.sival_int == 4711);
114
115 _exit(78);
116 }
fd38203a 117
151b9b96 118 assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
baf76283 119 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
3ecb3bdc
LP
120 assert_se(sd_event_source_set_child_process_own(p, true) >= 0);
121
122 /* We can't use structured initialization here, since the structure contains various unions and these
123 * fields lie in overlapping (carefully aligned) unions that LLVM is allergic to allow assignments
124 * to */
125 zero(plain_si);
126 plain_si.si_signo = SIGUSR2;
127 plain_si.si_code = SI_QUEUE;
19b761a0 128 plain_si.si_pid = getpid_cached();
3ecb3bdc
LP
129 plain_si.si_uid = getuid();
130 plain_si.si_value.sival_int = 4711;
131
132 assert_se(sd_event_source_send_child_signal(p, SIGUSR2, &plain_si, 0) >= 0);
fd38203a
LP
133
134 sd_event_source_unref(s);
135
136 return 1;
137}
138
139static int defer_handler(sd_event_source *s, void *userdata) {
39883f62 140 sd_event_source *p = NULL;
fd38203a 141
0c0cdb06 142 assert_se(s);
fd38203a
LP
143
144 log_info("got defer on %c", PTR_TO_INT(userdata));
145
0c0cdb06 146 assert_se(userdata == INT_TO_PTR('d'));
fd38203a 147
db7136ec 148 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1) >= 0);
72c0a2c2 149
151b9b96 150 assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
baf76283 151 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
fd38203a
LP
152 raise(SIGUSR1);
153
154 sd_event_source_unref(s);
155
156 return 1;
157}
158
3ecb3bdc 159static bool do_quit;
fd38203a
LP
160
161static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
162 log_info("got timer on %c", PTR_TO_INT(userdata));
163
164 if (userdata == INT_TO_PTR('c')) {
165
166 if (do_quit) {
167 sd_event_source *p;
168
151b9b96 169 assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0);
baf76283 170 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
fd38203a 171 } else {
0c0cdb06 172 assert_se(!got_c);
fd38203a
LP
173 got_c = true;
174 }
175 } else
04499a70 176 assert_not_reached();
fd38203a
LP
177
178 return 2;
179}
180
6203e07a 181static bool got_exit = false;
da7e457c 182
6203e07a 183static int exit_handler(sd_event_source *s, void *userdata) {
da7e457c
LP
184 log_info("got quit handler on %c", PTR_TO_INT(userdata));
185
6203e07a 186 got_exit = true;
da7e457c
LP
187
188 return 3;
189}
190
509a07ad
EV
191static bool got_post = false;
192
193static int post_handler(sd_event_source *s, void *userdata) {
194 log_info("got post handler");
195
196 got_post = true;
197
198 return 2;
199}
200
68da8adf 201static void test_basic_one(bool with_pidfd) {
fd38203a 202 sd_event *e = NULL;
12179984 203 sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL;
fd38203a 204 static const char ch = 'x';
71136404
LP
205 int a[2] = EBADF_PAIR, b[2] = EBADF_PAIR,
206 d[2] = EBADF_PAIR, k[2] = EBADF_PAIR;
591df2b5 207 uint64_t event_now;
6680b8d1 208 int64_t priority;
fd38203a 209
7fe11e84
YW
210 log_info("/* %s(pidfd=%s) */", __func__, yes_no(with_pidfd));
211
3ecb3bdc
LP
212 assert_se(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1) >= 0);
213
fd38203a
LP
214 assert_se(pipe(a) >= 0);
215 assert_se(pipe(b) >= 0);
9ec9694c 216 assert_se(pipe(d) >= 0);
12179984 217 assert_se(pipe(k) >= 0);
fd38203a 218
afc6adb5 219 assert_se(sd_event_default(&e) >= 0);
591df2b5 220 assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
fd38203a 221
cde93897
LP
222 assert_se(sd_event_set_watchdog(e, true) >= 0);
223
12179984
LP
224 /* Test whether we cleanly can destroy an io event source from its own handler */
225 got_unref = false;
151b9b96 226 assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0);
12179984 227 assert_se(write(k[1], &ch, 1) == 1);
f5fbe71d 228 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
12179984
LP
229 assert_se(got_unref);
230
9ec9694c
DS
231 got_a = false, got_b = false, got_c = false, got_d = 0;
232
254d1313 233 /* Add a oneshot handler, trigger it, reenable it, and trigger it again. */
151b9b96 234 assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
9ec9694c
DS
235 assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
236 assert_se(write(d[1], &ch, 1) >= 0);
f5fbe71d 237 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
9ec9694c
DS
238 assert_se(got_d == 1);
239 assert_se(write(d[1], &ch, 1) >= 0);
f5fbe71d 240 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
9ec9694c 241 assert_se(got_d == 2);
fd38203a 242
151b9b96
LP
243 assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0);
244 assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0);
3ecb3bdc
LP
245
246 do_quit = false;
6a0f1f6d 247 assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0);
151b9b96 248 assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0);
fd38203a
LP
249
250 assert_se(sd_event_source_set_priority(x, 99) >= 0);
6680b8d1
ME
251 assert_se(sd_event_source_get_priority(x, &priority) >= 0);
252 assert_se(priority == 99);
baf76283 253 assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0);
fd38203a
LP
254 assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0);
255 assert_se(sd_event_source_set_priority(z, 50) >= 0);
baf76283 256 assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
fd38203a 257 assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
a71fe8b8
LP
258
259 /* Test for floating event sources */
db7136ec 260 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1) >= 0);
a71fe8b8 261 assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
fd38203a
LP
262
263 assert_se(write(a[1], &ch, 1) >= 0);
264 assert_se(write(b[1], &ch, 1) >= 0);
265
266 assert_se(!got_a && !got_b && !got_c);
267
f5fbe71d 268 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
fd38203a
LP
269
270 assert_se(!got_a && got_b && !got_c);
271
f5fbe71d 272 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
fd38203a
LP
273
274 assert_se(!got_a && got_b && got_c);
275
f5fbe71d 276 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
fd38203a
LP
277
278 assert_se(got_a && got_b && got_c);
279
280 sd_event_source_unref(x);
281 sd_event_source_unref(y);
282
283 do_quit = true;
509a07ad 284 assert_se(sd_event_add_post(e, NULL, post_handler, NULL) >= 0);
591df2b5
EV
285 assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
286 assert_se(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC) >= 0);
baf76283 287 assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
fd38203a
LP
288
289 assert_se(sd_event_loop(e) >= 0);
509a07ad 290 assert_se(got_post);
5657c75f 291 assert_se(got_exit);
fd38203a
LP
292
293 sd_event_source_unref(z);
da7e457c 294 sd_event_source_unref(q);
fd38203a 295
d5e4ec5b
LP
296 sd_event_source_unref(w);
297
fd38203a
LP
298 sd_event_unref(e);
299
3d94f76c
LP
300 safe_close_pair(a);
301 safe_close_pair(b);
302 safe_close_pair(d);
303 safe_close_pair(k);
3ecb3bdc
LP
304
305 assert_se(unsetenv("SYSTEMD_PIDFD") >= 0);
9da4cb2b
LP
306}
307
68da8adf
JJ
308TEST(basic) {
309 test_basic_one(true); /* test with pidfd */
310 test_basic_one(false); /* test without pidfd */
311}
312
313TEST(sd_event_now) {
2c86ba5a
ZJS
314 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
315 uint64_t event_now;
316
317 assert_se(sd_event_new(&e) >= 0);
318 assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
319 assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0);
320 assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) > 0);
ba4e0427
LP
321 assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0);
322 assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) > 0);
2c86ba5a
ZJS
323 assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
324 assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
325
326 assert_se(sd_event_run(e, 0) == 0);
327
328 assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
329 assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) == 0);
330 assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) == 0);
ba4e0427
LP
331 assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0);
332 assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0);
2c86ba5a
ZJS
333 assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
334 assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
335}
336
9da4cb2b
LP
337static int last_rtqueue_sigval = 0;
338static int n_rtqueue = 0;
339
340static int rtqueue_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
341 last_rtqueue_sigval = si->ssi_int;
313cefa1 342 n_rtqueue++;
9da4cb2b
LP
343 return 0;
344}
345
68da8adf 346TEST(rtqueue) {
9da4cb2b
LP
347 sd_event_source *u = NULL, *v = NULL, *s = NULL;
348 sd_event *e = NULL;
349
350 assert_se(sd_event_default(&e) >= 0);
351
db7136ec 352 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2) >= 0);
9da4cb2b
LP
353 assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0);
354 assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0);
355 assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0);
356
357 assert_se(sd_event_source_set_priority(v, -10) >= 0);
358
19500112
YW
359 assert_se(sigqueue(getpid_cached(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0);
360 assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0);
361 assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0);
362 assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0);
363 assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0);
9da4cb2b
LP
364
365 assert_se(n_rtqueue == 0);
366 assert_se(last_rtqueue_sigval == 0);
367
f5fbe71d 368 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
9da4cb2b
LP
369 assert_se(n_rtqueue == 1);
370 assert_se(last_rtqueue_sigval == 2); /* first SIGRTMIN+3 */
371
f5fbe71d 372 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
9da4cb2b
LP
373 assert_se(n_rtqueue == 2);
374 assert_se(last_rtqueue_sigval == 4); /* second SIGRTMIN+3 */
375
f5fbe71d 376 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
9da4cb2b
LP
377 assert_se(n_rtqueue == 3);
378 assert_se(last_rtqueue_sigval == 3); /* first SIGUSR2 */
379
f5fbe71d 380 assert_se(sd_event_run(e, UINT64_MAX) >= 1);
9da4cb2b
LP
381 assert_se(n_rtqueue == 4);
382 assert_se(last_rtqueue_sigval == 1); /* SIGRTMIN+2 */
383
384 assert_se(sd_event_run(e, 0) == 0); /* the other SIGUSR2 is dropped, because the first one was still queued */
385 assert_se(n_rtqueue == 4);
386 assert_se(last_rtqueue_sigval == 1);
387
388 sd_event_source_unref(u);
389 sd_event_source_unref(v);
390 sd_event_source_unref(s);
391
392 sd_event_unref(e);
393}
394
41e09d62
LP
395#define CREATE_EVENTS_MAX (70000U)
396
397struct inotify_context {
398 bool delete_self_handler_called;
399 unsigned create_called[CREATE_EVENTS_MAX];
400 unsigned create_overflow;
401 unsigned n_create_events;
4a7cd0ca 402 const char *path;
41e09d62
LP
403};
404
405static void maybe_exit(sd_event_source *s, struct inotify_context *c) {
406 unsigned n;
407
f21b863e
YW
408 assert_se(s);
409 assert_se(c);
41e09d62
LP
410
411 if (!c->delete_self_handler_called)
412 return;
413
414 for (n = 0; n < 3; n++) {
415 unsigned i;
416
417 if (c->create_overflow & (1U << n))
418 continue;
419
420 for (i = 0; i < c->n_create_events; i++)
421 if (!(c->create_called[i] & (1U << n)))
422 return;
423 }
424
425 sd_event_exit(sd_event_source_get_event(s), 0);
426}
427
428static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
4a7cd0ca
YW
429 struct inotify_context *c = ASSERT_PTR(userdata);
430 const char *path, *description;
41e09d62
LP
431 unsigned bit, n;
432
4a7cd0ca
YW
433 assert_se(sd_event_source_get_inotify_path(s, &path) >= 0);
434
41e09d62
LP
435 assert_se(sd_event_source_get_description(s, &description) >= 0);
436 assert_se(safe_atou(description, &n) >= 0);
437
438 assert_se(n <= 3);
439 bit = 1U << n;
440
441 if (ev->mask & IN_Q_OVERFLOW) {
4a7cd0ca 442 log_info("inotify-handler for %s <%s>: overflow", path, description);
41e09d62
LP
443 c->create_overflow |= bit;
444 } else if (ev->mask & IN_CREATE) {
4a7cd0ca 445 assert_se(path_equal_or_inode_same(path, c->path, 0));
834f3ba1 446 if (streq(ev->name, "sub"))
4a7cd0ca 447 log_debug("inotify-handler for %s <%s>: create on %s", path, description, ev->name);
834f3ba1
YW
448 else {
449 unsigned i;
41e09d62 450
41e09d62 451 assert_se(safe_atou(ev->name, &i) >= 0);
41e09d62
LP
452 assert_se(i < c->n_create_events);
453 c->create_called[i] |= bit;
454 }
455 } else if (ev->mask & IN_DELETE) {
4a7cd0ca 456 log_info("inotify-handler for %s <%s>: delete of %s", path, description, ev->name);
41e09d62
LP
457 assert_se(streq(ev->name, "sub"));
458 } else
04499a70 459 assert_not_reached();
41e09d62
LP
460
461 maybe_exit(s, c);
462 return 1;
463}
464
465static int delete_self_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
4a7cd0ca
YW
466 struct inotify_context *c = ASSERT_PTR(userdata);
467 const char *path;
468
469 assert_se(sd_event_source_get_inotify_path(s, &path) >= 0);
41e09d62
LP
470
471 if (ev->mask & IN_Q_OVERFLOW) {
4a7cd0ca 472 log_info("delete-self-handler for %s: overflow", path);
41e09d62
LP
473 c->delete_self_handler_called = true;
474 } else if (ev->mask & IN_DELETE_SELF) {
4a7cd0ca 475 log_info("delete-self-handler for %s: delete-self", path);
41e09d62
LP
476 c->delete_self_handler_called = true;
477 } else if (ev->mask & IN_IGNORED) {
4a7cd0ca 478 log_info("delete-self-handler for %s: ignore", path);
41e09d62 479 } else
04499a70 480 assert_not_reached();
41e09d62
LP
481
482 maybe_exit(s, c);
483 return 1;
484}
485
68da8adf 486static void test_inotify_one(unsigned n_create_events) {
41e09d62
LP
487 _cleanup_(rm_rf_physical_and_freep) char *p = NULL;
488 sd_event_source *a = NULL, *b = NULL, *c = NULL, *d = NULL;
489 struct inotify_context context = {
490 .n_create_events = n_create_events,
491 };
492 sd_event *e = NULL;
4a7cd0ca 493 const char *q, *pp;
41e09d62
LP
494 unsigned i;
495
7fe11e84
YW
496 log_info("/* %s(%u) */", __func__, n_create_events);
497
41e09d62
LP
498 assert_se(sd_event_default(&e) >= 0);
499
500 assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0);
4a7cd0ca 501 context.path = p;
41e09d62
LP
502
503 assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0);
504 assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0);
505 assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_IDLE) >= 0);
506 assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_NORMAL) >= 0);
507 assert_se(sd_event_add_inotify(e, &c, p, IN_CREATE|IN_DELETE|IN_EXCL_UNLINK, inotify_handler, &context) >= 0);
508 assert_se(sd_event_source_set_priority(c, SD_EVENT_PRIORITY_IDLE) >= 0);
509
510 assert_se(sd_event_source_set_description(a, "0") >= 0);
511 assert_se(sd_event_source_set_description(b, "1") >= 0);
512 assert_se(sd_event_source_set_description(c, "2") >= 0);
513
74c4231c
YW
514 assert_se(sd_event_source_get_inotify_path(a, &pp) >= 0);
515 assert_se(path_equal_or_inode_same(pp, p, 0));
74c4231c
YW
516 assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0);
517 assert_se(path_equal_or_inode_same(pp, p, 0));
74c4231c
YW
518 assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0);
519 assert_se(path_equal_or_inode_same(pp, p, 0));
74c4231c 520
41e09d62
LP
521 q = strjoina(p, "/sub");
522 assert_se(touch(q) >= 0);
523 assert_se(sd_event_add_inotify(e, &d, q, IN_DELETE_SELF, delete_self_handler, &context) >= 0);
524
525 for (i = 0; i < n_create_events; i++) {
526 char buf[DECIMAL_STR_MAX(unsigned)+1];
3d41b6b8 527 _cleanup_free_ char *z = NULL;
41e09d62
LP
528
529 xsprintf(buf, "%u", i);
657ee2d8 530 assert_se(z = path_join(p, buf));
41e09d62
LP
531
532 assert_se(touch(z) >= 0);
533 }
534
535 assert_se(unlink(q) >= 0);
536
537 assert_se(sd_event_loop(e) >= 0);
538
539 sd_event_source_unref(a);
540 sd_event_source_unref(b);
541 sd_event_source_unref(c);
542 sd_event_source_unref(d);
543
544 sd_event_unref(e);
545}
546
68da8adf
JJ
547TEST(inotify) {
548 test_inotify_one(100); /* should work without overflow */
549 test_inotify_one(33000); /* should trigger a q overflow */
550}
551
3ecb3bdc
LP
552static int pidfd_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
553 assert_se(s);
554 assert_se(si);
555
556 assert_se(si->si_uid == getuid());
557 assert_se(si->si_signo == SIGCHLD);
558 assert_se(si->si_code == CLD_EXITED);
559 assert_se(si->si_status == 66);
560
561 log_info("got pidfd on %c", PTR_TO_INT(userdata));
562
563 assert_se(userdata == INT_TO_PTR('p'));
564
565 assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
566 sd_event_source_unref(s);
567
568 return 0;
569}
570
68da8adf 571TEST(pidfd) {
3ecb3bdc
LP
572 sd_event_source *s = NULL, *t = NULL;
573 sd_event *e = NULL;
574 int pidfd;
575 pid_t pid, pid2;
576
db7136ec 577 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
3ecb3bdc
LP
578
579 pid = fork();
d7a0f1f4 580 if (pid == 0)
3ecb3bdc
LP
581 /* child */
582 _exit(66);
3ecb3bdc
LP
583
584 assert_se(pid > 1);
585
586 pidfd = pidfd_open(pid, 0);
587 if (pidfd < 0) {
588 /* No pidfd_open() supported or blocked? */
589 assert_se(ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno));
590 (void) wait_for_terminate(pid, NULL);
591 return;
592 }
593
594 pid2 = fork();
595 if (pid2 == 0)
596 freeze();
597
598 assert_se(pid > 2);
599
600 assert_se(sd_event_default(&e) >= 0);
601 assert_se(sd_event_add_child_pidfd(e, &s, pidfd, WEXITED, pidfd_handler, INT_TO_PTR('p')) >= 0);
602 assert_se(sd_event_source_set_child_pidfd_own(s, true) >= 0);
603
604 /* This one should never trigger, since our second child lives forever */
605 assert_se(sd_event_add_child(e, &t, pid2, WEXITED, pidfd_handler, INT_TO_PTR('q')) >= 0);
606 assert_se(sd_event_source_set_child_process_own(t, true) >= 0);
607
608 assert_se(sd_event_loop(e) >= 0);
609
610 /* Child should still be alive */
611 assert_se(kill(pid2, 0) >= 0);
612
613 t = sd_event_source_unref(t);
614
615 /* Child should now be dead, since we dropped the ref */
616 assert_se(kill(pid2, 0) < 0 && errno == ESRCH);
617
618 sd_event_unref(e);
619}
620
68d89065
MS
621static int ratelimit_io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
622 unsigned *c = (unsigned*) userdata;
623 *c += 1;
624 return 0;
625}
626
627static int ratelimit_time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
628 int r;
629
630 r = sd_event_source_set_enabled(s, SD_EVENT_ON);
631 if (r < 0)
632 log_warning_errno(r, "Failed to turn on notify event source: %m");
633
634 r = sd_event_source_set_time(s, usec + 1000);
635 if (r < 0)
636 log_error_errno(r, "Failed to restart watchdog event source: %m");
637
638 unsigned *c = (unsigned*) userdata;
639 *c += 1;
640
641 return 0;
642}
643
fd69f224
MS
644static int expired = -1;
645static int ratelimit_expired(sd_event_source *s, void *userdata) {
646 return ++expired;
647}
648
68da8adf 649TEST(ratelimit) {
71136404 650 _cleanup_close_pair_ int p[2] = EBADF_PAIR;
68d89065
MS
651 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
652 _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
653 uint64_t interval;
654 unsigned count, burst;
655
656 assert_se(sd_event_default(&e) >= 0);
657 assert_se(pipe2(p, O_CLOEXEC|O_NONBLOCK) >= 0);
658
659 assert_se(sd_event_add_io(e, &s, p[0], EPOLLIN, ratelimit_io_handler, &count) >= 0);
660 assert_se(sd_event_source_set_description(s, "test-ratelimit-io") >= 0);
661 assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
662 assert_se(sd_event_source_get_ratelimit(s, &interval, &burst) >= 0);
663 assert_se(interval == 1 * USEC_PER_SEC && burst == 5);
664
665 assert_se(write(p[1], "1", 1) == 1);
666
667 count = 0;
668 for (unsigned i = 0; i < 10; i++) {
669 log_debug("slow loop iteration %u", i);
670 assert_se(sd_event_run(e, UINT64_MAX) >= 0);
4251512e 671 assert_se(usleep_safe(250 * USEC_PER_MSEC) >= 0);
68d89065
MS
672 }
673
674 assert_se(sd_event_source_is_ratelimited(s) == 0);
675 assert_se(count == 10);
c0f86d66 676 log_info("ratelimit_io_handler: called %u times, event source not ratelimited", count);
68d89065
MS
677
678 assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
679 assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
680
681 count = 0;
682 for (unsigned i = 0; i < 10; i++) {
683 log_debug("fast event loop iteration %u", i);
684 assert_se(sd_event_run(e, UINT64_MAX) >= 0);
4251512e 685 assert_se(usleep_safe(10) >= 0);
68d89065 686 }
c0f86d66 687 log_info("ratelimit_io_handler: called %u times, event source got ratelimited", count);
68d89065
MS
688 assert_se(count < 10);
689
690 s = sd_event_source_unref(s);
691 safe_close_pair(p);
692
693 count = 0;
694 assert_se(sd_event_add_time_relative(e, &s, CLOCK_MONOTONIC, 1000, 1, ratelimit_time_handler, &count) >= 0);
695 assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) == 0);
696
697 do {
698 assert_se(sd_event_run(e, UINT64_MAX) >= 0);
699 } while (!sd_event_source_is_ratelimited(s));
700
c0f86d66 701 log_info("ratelimit_time_handler: called %u times, event source got ratelimited", count);
68d89065
MS
702 assert_se(count == 10);
703
da115b93 704 /* In order to get rid of active rate limit client needs to disable it explicitly */
68d89065
MS
705 assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
706 assert_se(!sd_event_source_is_ratelimited(s));
707
708 assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) >= 0);
709
fd69f224
MS
710 /* Set callback that will be invoked when we leave rate limited state. */
711 assert_se(sd_event_source_set_ratelimit_expire_callback(s, ratelimit_expired) >= 0);
712
68d89065
MS
713 do {
714 assert_se(sd_event_run(e, UINT64_MAX) >= 0);
715 } while (!sd_event_source_is_ratelimited(s));
716
717 log_info("ratelimit_time_handler: called 10 more times, event source got ratelimited");
718 assert_se(count == 20);
fd69f224
MS
719
720 /* Dispatch the event loop once more and check that ratelimit expiration callback got called */
721 assert_se(sd_event_run(e, UINT64_MAX) >= 0);
722 assert_se(expired == 0);
68d89065
MS
723}
724
68da8adf 725TEST(simple_timeout) {
c14e57ba
LP
726 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
727 usec_t f, t, some_time;
728
729 some_time = random_u64_range(2 * USEC_PER_SEC);
730
731 assert_se(sd_event_default(&e) >= 0);
732
733 assert_se(sd_event_prepare(e) == 0);
734
735 f = now(CLOCK_MONOTONIC);
736 assert_se(sd_event_wait(e, some_time) >= 0);
737 t = now(CLOCK_MONOTONIC);
738
739 /* The event loop may sleep longer than the specified time (timer accuracy, scheduling latencies, …),
740 * but never shorter. Let's check that. */
741 assert_se(t >= usec_add(f, some_time));
742}
743
035daf73
LP
744static int inotify_self_destroy_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
745 sd_event_source **p = userdata;
746
747 assert_se(ev);
748 assert_se(p);
749 assert_se(*p == s);
750
751 assert_se(FLAGS_SET(ev->mask, IN_ATTRIB));
752
753 assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
754
755 *p = sd_event_source_unref(*p); /* here's what we actually intend to test: we destroy the event
756 * source from inside the event source handler */
757 return 1;
758}
759
68da8adf 760TEST(inotify_self_destroy) {
035daf73
LP
761 _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
762 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
763 char path[] = "/tmp/inotifyXXXXXX";
254d1313 764 _cleanup_close_ int fd = -EBADF;
035daf73
LP
765
766 /* Tests that destroying an inotify event source from its own handler is safe */
767
768 assert_se(sd_event_default(&e) >= 0);
769
770 fd = mkostemp_safe(path);
771 assert_se(fd >= 0);
772 assert_se(sd_event_add_inotify_fd(e, &s, fd, IN_ATTRIB, inotify_self_destroy_handler, &s) >= 0);
773 fd = safe_close(fd);
774 assert_se(unlink(path) >= 0); /* This will trigger IN_ATTRIB because link count goes to zero */
775 assert_se(sd_event_loop(e) >= 0);
776}
777
c7b5a5a7
YW
778struct inotify_process_buffered_data_context {
779 const char *path[2];
780 unsigned i;
781};
782
783static int inotify_process_buffered_data_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
784 struct inotify_process_buffered_data_context *c = ASSERT_PTR(userdata);
785 const char *description;
786
787 assert_se(sd_event_source_get_description(s, &description) >= 0);
788
789 assert_se(c->i < 2);
790 assert_se(streq(c->path[c->i], description));
791 c->i++;
792
793 return 1;
794}
795
796TEST(inotify_process_buffered_data) {
797 _cleanup_(rm_rf_physical_and_freep) char *p = NULL, *q = NULL;
798 _cleanup_(sd_event_source_unrefp) sd_event_source *a = NULL, *b = NULL;
799 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
800 _cleanup_free_ char *z = NULL;
801
802 /* For issue #23826 */
803
804 assert_se(sd_event_default(&e) >= 0);
805
806 assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0);
807 assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &q) >= 0);
808
809 struct inotify_process_buffered_data_context context = {
810 .path = { p, q },
811 };
812
813 assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE, inotify_process_buffered_data_handler, &context) >= 0);
814 assert_se(sd_event_add_inotify(e, &b, q, IN_CREATE, inotify_process_buffered_data_handler, &context) >= 0);
815
816 assert_se(z = path_join(p, "aaa"));
817 assert_se(touch(z) >= 0);
818 z = mfree(z);
819 assert_se(z = path_join(q, "bbb"));
820 assert_se(touch(z) >= 0);
821 z = mfree(z);
822
823 assert_se(sd_event_run(e, 10 * USEC_PER_SEC) > 0);
824 assert_se(sd_event_prepare(e) > 0); /* issue #23826: this was 0. */
825 assert_se(sd_event_dispatch(e) > 0);
826 assert_se(sd_event_prepare(e) == 0);
827 assert_se(sd_event_wait(e, 0) == 0);
828}
829
2eeff0f4
LB
830TEST(fork) {
831 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
832 int r;
833
834 assert_se(sd_event_default(&e) >= 0);
835 assert_se(sd_event_prepare(e) == 0);
836
837 /* Check that after a fork the cleanup functions return NULL */
838 r = safe_fork("(bus-fork-test)", FORK_WAIT|FORK_LOG, NULL);
839 if (r == 0) {
840 assert_se(e);
841 assert_se(sd_event_ref(e) == NULL);
842 assert_se(sd_event_unref(e) == NULL);
843 _exit(EXIT_SUCCESS);
844 }
845
846 assert_se(r >= 0);
847}
848
2fa48059
YW
849TEST(sd_event_source_set_io_fd) {
850 _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
851 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
852 _cleanup_close_pair_ int pfd_a[2] = EBADF_PAIR, pfd_b[2] = EBADF_PAIR;
853
854 assert_se(sd_event_default(&e) >= 0);
855
856 assert_se(pipe2(pfd_a, O_CLOEXEC) >= 0);
857 assert_se(pipe2(pfd_b, O_CLOEXEC) >= 0);
858
859 assert_se(sd_event_add_io(e, &s, pfd_a[0], EPOLLIN, NULL, INT_TO_PTR(-ENOANO)) >= 0);
860 assert_se(sd_event_source_set_io_fd_own(s, true) >= 0);
861 TAKE_FD(pfd_a[0]);
862
863 assert_se(sd_event_source_set_io_fd(s, pfd_b[0]) >= 0);
864 TAKE_FD(pfd_b[0]);
865}
866
2fdc274c
LP
867static int hup_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
868 unsigned *c = userdata;
869
870 assert_se(revents == EPOLLHUP);
871
872 (*c)++;
873 return 0;
874}
875
876TEST(leave_ratelimit) {
877 bool expect_ratelimit = false, manually_left_ratelimit = false;
878 _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
879 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
71136404 880 _cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
2fdc274c
LP
881 unsigned c = 0;
882 int r;
883
884 assert_se(sd_event_default(&e) >= 0);
885
9a27ef09 886 /* Create an event source that will continuously fire by creating a pipe whose write side is closed,
2fdc274c
LP
887 * and which hence will only see EOF and constant EPOLLHUP */
888 assert_se(pipe2(pfd, O_CLOEXEC) >= 0);
889 assert_se(sd_event_add_io(e, &s, pfd[0], EPOLLIN, hup_callback, &c) >= 0);
890 assert_se(sd_event_source_set_io_fd_own(s, true) >= 0);
891 assert_se(sd_event_source_set_ratelimit(s, 5*USEC_PER_MINUTE, 5) >= 0);
892
893 pfd[0] = -EBADF;
9a27ef09 894 pfd[1] = safe_close(pfd[1]); /* Trigger continuous EOF */
2fdc274c
LP
895
896 for (;;) {
897 r = sd_event_prepare(e);
898 assert_se(r >= 0);
899
900 if (r == 0) {
901 r = sd_event_wait(e, UINT64_MAX);
902 assert_se(r > 0);
903 }
904
905 r = sd_event_dispatch(e);
906 assert_se(r > 0);
907
908 r = sd_event_source_is_ratelimited(s);
909 assert_se(r >= 0);
910
911 if (c < 5)
912 /* First four dispatches should just work */
913 assert_se(!r);
914 else if (c == 5) {
915 /* The fifth dispatch should still work, but we now expect the ratelimit to be hit subsequently */
916 if (!expect_ratelimit) {
917 assert_se(!r);
918 assert_se(sd_event_source_leave_ratelimit(s) == 0); /* this should be a NOP, and return 0 hence */
919 expect_ratelimit = true;
920 } else {
921 /* We expected the ratelimit, let's leave it manually, and verify it */
922 assert_se(r);
923 assert_se(sd_event_source_leave_ratelimit(s) > 0); /* we are ratelimited, hence should return > 0 */
924 assert_se(sd_event_source_is_ratelimited(s) == 0);
925
926 manually_left_ratelimit = true;
927 }
928
929 } else if (c == 6)
930 /* On the sixth iteration let's just exit */
931 break;
932 }
933
934 /* Verify we definitely hit the ratelimit and left it manually again */
935 assert_se(manually_left_ratelimit);
936}
937
68da8adf 938DEFINE_TEST_MAIN(LOG_DEBUG);