]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
fd38203a | 2 | |
fe993888 MS |
3 | #include <sys/wait.h> |
4 | ||
fd38203a | 5 | #include "sd-event.h" |
3ffd4af2 | 6 | |
41e09d62 | 7 | #include "alloc-util.h" |
3ffd4af2 | 8 | #include "fd-util.h" |
41e09d62 | 9 | #include "fs-util.h" |
fd38203a | 10 | #include "log.h" |
0c0cdb06 | 11 | #include "macro.h" |
41e09d62 LP |
12 | #include "parse-util.h" |
13 | #include "process-util.h" | |
14 | #include "rm-rf.h" | |
24882e06 | 15 | #include "signal-util.h" |
41e09d62 LP |
16 | #include "stdio-util.h" |
17 | #include "string-util.h" | |
6d7c4033 | 18 | #include "tests.h" |
e4de7287 | 19 | #include "tmpfile-util.h" |
3ffd4af2 | 20 | #include "util.h" |
fd38203a LP |
21 | |
22 | static int prepare_handler(sd_event_source *s, void *userdata) { | |
23 | log_info("preparing %c", PTR_TO_INT(userdata)); | |
24 | return 1; | |
25 | } | |
26 | ||
12179984 | 27 | static bool got_a, got_b, got_c, got_unref; |
9ec9694c | 28 | static unsigned got_d; |
fd38203a | 29 | |
12179984 LP |
30 | static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { |
31 | sd_event_source_unref(s); | |
32 | got_unref = true; | |
33 | return 0; | |
34 | } | |
35 | ||
fd38203a LP |
36 | static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { |
37 | ||
38 | log_info("got IO on %c", PTR_TO_INT(userdata)); | |
39 | ||
40 | if (userdata == INT_TO_PTR('a')) { | |
baf76283 | 41 | assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); |
fd38203a LP |
42 | assert_se(!got_a); |
43 | got_a = true; | |
44 | } else if (userdata == INT_TO_PTR('b')) { | |
45 | assert_se(!got_b); | |
46 | got_b = true; | |
9ec9694c DS |
47 | } else if (userdata == INT_TO_PTR('d')) { |
48 | got_d++; | |
49 | if (got_d < 2) | |
50 | assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0); | |
51 | else | |
52 | assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); | |
fd38203a LP |
53 | } else |
54 | assert_not_reached("Yuck!"); | |
55 | ||
56 | return 1; | |
57 | } | |
58 | ||
59 | static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) { | |
60 | ||
0c0cdb06 RC |
61 | assert_se(s); |
62 | assert_se(si); | |
fd38203a LP |
63 | |
64 | log_info("got child on %c", PTR_TO_INT(userdata)); | |
65 | ||
0c0cdb06 | 66 | assert_se(userdata == INT_TO_PTR('f')); |
fd38203a | 67 | |
6203e07a | 68 | assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0); |
fd38203a LP |
69 | sd_event_source_unref(s); |
70 | ||
71 | return 1; | |
72 | } | |
73 | ||
74 | static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { | |
39883f62 | 75 | sd_event_source *p = NULL; |
fd38203a LP |
76 | pid_t pid; |
77 | ||
0c0cdb06 RC |
78 | assert_se(s); |
79 | assert_se(si); | |
fd38203a LP |
80 | |
81 | log_info("got signal on %c", PTR_TO_INT(userdata)); | |
82 | ||
0c0cdb06 | 83 | assert_se(userdata == INT_TO_PTR('e')); |
fd38203a | 84 | |
72c0a2c2 | 85 | assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); |
fd38203a LP |
86 | |
87 | pid = fork(); | |
88 | assert_se(pid >= 0); | |
89 | ||
90 | if (pid == 0) | |
a45d7127 | 91 | _exit(EXIT_SUCCESS); |
fd38203a | 92 | |
151b9b96 | 93 | assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0); |
baf76283 | 94 | assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); |
fd38203a LP |
95 | |
96 | sd_event_source_unref(s); | |
97 | ||
98 | return 1; | |
99 | } | |
100 | ||
101 | static int defer_handler(sd_event_source *s, void *userdata) { | |
39883f62 | 102 | sd_event_source *p = NULL; |
fd38203a | 103 | |
0c0cdb06 | 104 | assert_se(s); |
fd38203a LP |
105 | |
106 | log_info("got defer on %c", PTR_TO_INT(userdata)); | |
107 | ||
0c0cdb06 | 108 | assert_se(userdata == INT_TO_PTR('d')); |
fd38203a | 109 | |
72c0a2c2 LP |
110 | assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0); |
111 | ||
151b9b96 | 112 | assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0); |
baf76283 | 113 | assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); |
fd38203a LP |
114 | raise(SIGUSR1); |
115 | ||
116 | sd_event_source_unref(s); | |
117 | ||
118 | return 1; | |
119 | } | |
120 | ||
121 | static bool do_quit = false; | |
122 | ||
123 | static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) { | |
124 | log_info("got timer on %c", PTR_TO_INT(userdata)); | |
125 | ||
126 | if (userdata == INT_TO_PTR('c')) { | |
127 | ||
128 | if (do_quit) { | |
129 | sd_event_source *p; | |
130 | ||
151b9b96 | 131 | assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0); |
baf76283 | 132 | assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); |
fd38203a | 133 | } else { |
0c0cdb06 | 134 | assert_se(!got_c); |
fd38203a LP |
135 | got_c = true; |
136 | } | |
137 | } else | |
138 | assert_not_reached("Huh?"); | |
139 | ||
140 | return 2; | |
141 | } | |
142 | ||
6203e07a | 143 | static bool got_exit = false; |
da7e457c | 144 | |
6203e07a | 145 | static int exit_handler(sd_event_source *s, void *userdata) { |
da7e457c LP |
146 | log_info("got quit handler on %c", PTR_TO_INT(userdata)); |
147 | ||
6203e07a | 148 | got_exit = true; |
da7e457c LP |
149 | |
150 | return 3; | |
151 | } | |
152 | ||
509a07ad EV |
153 | static bool got_post = false; |
154 | ||
155 | static int post_handler(sd_event_source *s, void *userdata) { | |
156 | log_info("got post handler"); | |
157 | ||
158 | got_post = true; | |
159 | ||
160 | return 2; | |
161 | } | |
162 | ||
9da4cb2b | 163 | static void test_basic(void) { |
fd38203a | 164 | sd_event *e = NULL; |
12179984 | 165 | sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL; |
fd38203a | 166 | static const char ch = 'x'; |
12179984 | 167 | int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 }; |
591df2b5 | 168 | uint64_t event_now; |
6680b8d1 | 169 | int64_t priority; |
fd38203a LP |
170 | |
171 | assert_se(pipe(a) >= 0); | |
172 | assert_se(pipe(b) >= 0); | |
9ec9694c | 173 | assert_se(pipe(d) >= 0); |
12179984 | 174 | assert_se(pipe(k) >= 0); |
fd38203a | 175 | |
afc6adb5 | 176 | assert_se(sd_event_default(&e) >= 0); |
591df2b5 | 177 | assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0); |
fd38203a | 178 | |
cde93897 LP |
179 | assert_se(sd_event_set_watchdog(e, true) >= 0); |
180 | ||
12179984 LP |
181 | /* Test whether we cleanly can destroy an io event source from its own handler */ |
182 | got_unref = false; | |
151b9b96 | 183 | assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0); |
12179984 LP |
184 | assert_se(write(k[1], &ch, 1) == 1); |
185 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
186 | assert_se(got_unref); | |
187 | ||
9ec9694c DS |
188 | got_a = false, got_b = false, got_c = false, got_d = 0; |
189 | ||
3fe91079 | 190 | /* Add a oneshot handler, trigger it, reenable it, and trigger |
9ec9694c | 191 | * it again. */ |
151b9b96 | 192 | assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0); |
9ec9694c DS |
193 | assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0); |
194 | assert_se(write(d[1], &ch, 1) >= 0); | |
195 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
196 | assert_se(got_d == 1); | |
197 | assert_se(write(d[1], &ch, 1) >= 0); | |
198 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
199 | assert_se(got_d == 2); | |
fd38203a | 200 | |
151b9b96 LP |
201 | assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0); |
202 | assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0); | |
6a0f1f6d | 203 | assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0); |
151b9b96 | 204 | assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0); |
fd38203a LP |
205 | |
206 | assert_se(sd_event_source_set_priority(x, 99) >= 0); | |
6680b8d1 ME |
207 | assert_se(sd_event_source_get_priority(x, &priority) >= 0); |
208 | assert_se(priority == 99); | |
baf76283 | 209 | assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0); |
fd38203a LP |
210 | assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0); |
211 | assert_se(sd_event_source_set_priority(z, 50) >= 0); | |
baf76283 | 212 | assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); |
fd38203a | 213 | assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0); |
a71fe8b8 LP |
214 | |
215 | /* Test for floating event sources */ | |
72c0a2c2 | 216 | assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1, -1) >= 0); |
a71fe8b8 | 217 | assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0); |
fd38203a LP |
218 | |
219 | assert_se(write(a[1], &ch, 1) >= 0); | |
220 | assert_se(write(b[1], &ch, 1) >= 0); | |
221 | ||
222 | assert_se(!got_a && !got_b && !got_c); | |
223 | ||
224 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
225 | ||
226 | assert_se(!got_a && got_b && !got_c); | |
227 | ||
228 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
229 | ||
230 | assert_se(!got_a && got_b && got_c); | |
231 | ||
232 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
233 | ||
234 | assert_se(got_a && got_b && got_c); | |
235 | ||
236 | sd_event_source_unref(x); | |
237 | sd_event_source_unref(y); | |
238 | ||
239 | do_quit = true; | |
509a07ad | 240 | assert_se(sd_event_add_post(e, NULL, post_handler, NULL) >= 0); |
591df2b5 EV |
241 | assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0); |
242 | assert_se(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC) >= 0); | |
baf76283 | 243 | assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); |
fd38203a LP |
244 | |
245 | assert_se(sd_event_loop(e) >= 0); | |
509a07ad | 246 | assert_se(got_post); |
5657c75f | 247 | assert_se(got_exit); |
fd38203a LP |
248 | |
249 | sd_event_source_unref(z); | |
da7e457c | 250 | sd_event_source_unref(q); |
fd38203a | 251 | |
d5e4ec5b LP |
252 | sd_event_source_unref(w); |
253 | ||
fd38203a LP |
254 | sd_event_unref(e); |
255 | ||
3d94f76c LP |
256 | safe_close_pair(a); |
257 | safe_close_pair(b); | |
258 | safe_close_pair(d); | |
259 | safe_close_pair(k); | |
9da4cb2b LP |
260 | } |
261 | ||
2c86ba5a ZJS |
262 | static void test_sd_event_now(void) { |
263 | _cleanup_(sd_event_unrefp) sd_event *e = NULL; | |
264 | uint64_t event_now; | |
265 | ||
266 | assert_se(sd_event_new(&e) >= 0); | |
267 | assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0); | |
268 | assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0); | |
269 | assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) > 0); | |
3411372e LP |
270 | if (clock_boottime_supported()) { |
271 | assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0); | |
272 | assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) > 0); | |
273 | } | |
2c86ba5a ZJS |
274 | assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP); |
275 | assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP); | |
276 | ||
277 | assert_se(sd_event_run(e, 0) == 0); | |
278 | ||
279 | assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0); | |
280 | assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) == 0); | |
281 | assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) == 0); | |
3411372e LP |
282 | if (clock_boottime_supported()) { |
283 | assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0); | |
284 | assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0); | |
285 | } | |
2c86ba5a ZJS |
286 | assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP); |
287 | assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP); | |
288 | } | |
289 | ||
9da4cb2b LP |
290 | static int last_rtqueue_sigval = 0; |
291 | static int n_rtqueue = 0; | |
292 | ||
293 | static int rtqueue_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { | |
294 | last_rtqueue_sigval = si->ssi_int; | |
313cefa1 | 295 | n_rtqueue++; |
9da4cb2b LP |
296 | return 0; |
297 | } | |
298 | ||
299 | static void test_rtqueue(void) { | |
300 | sd_event_source *u = NULL, *v = NULL, *s = NULL; | |
301 | sd_event *e = NULL; | |
302 | ||
303 | assert_se(sd_event_default(&e) >= 0); | |
304 | ||
305 | assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0); | |
306 | assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0); | |
307 | assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0); | |
308 | assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0); | |
309 | ||
310 | assert_se(sd_event_source_set_priority(v, -10) >= 0); | |
311 | ||
19500112 YW |
312 | assert_se(sigqueue(getpid_cached(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0); |
313 | assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0); | |
314 | assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0); | |
315 | assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0); | |
316 | assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0); | |
9da4cb2b LP |
317 | |
318 | assert_se(n_rtqueue == 0); | |
319 | assert_se(last_rtqueue_sigval == 0); | |
320 | ||
321 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
322 | assert_se(n_rtqueue == 1); | |
323 | assert_se(last_rtqueue_sigval == 2); /* first SIGRTMIN+3 */ | |
324 | ||
325 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
326 | assert_se(n_rtqueue == 2); | |
327 | assert_se(last_rtqueue_sigval == 4); /* second SIGRTMIN+3 */ | |
328 | ||
329 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
330 | assert_se(n_rtqueue == 3); | |
331 | assert_se(last_rtqueue_sigval == 3); /* first SIGUSR2 */ | |
332 | ||
333 | assert_se(sd_event_run(e, (uint64_t) -1) >= 1); | |
334 | assert_se(n_rtqueue == 4); | |
335 | assert_se(last_rtqueue_sigval == 1); /* SIGRTMIN+2 */ | |
336 | ||
337 | assert_se(sd_event_run(e, 0) == 0); /* the other SIGUSR2 is dropped, because the first one was still queued */ | |
338 | assert_se(n_rtqueue == 4); | |
339 | assert_se(last_rtqueue_sigval == 1); | |
340 | ||
341 | sd_event_source_unref(u); | |
342 | sd_event_source_unref(v); | |
343 | sd_event_source_unref(s); | |
344 | ||
345 | sd_event_unref(e); | |
346 | } | |
347 | ||
41e09d62 LP |
348 | #define CREATE_EVENTS_MAX (70000U) |
349 | ||
350 | struct inotify_context { | |
351 | bool delete_self_handler_called; | |
352 | unsigned create_called[CREATE_EVENTS_MAX]; | |
353 | unsigned create_overflow; | |
354 | unsigned n_create_events; | |
355 | }; | |
356 | ||
357 | static void maybe_exit(sd_event_source *s, struct inotify_context *c) { | |
358 | unsigned n; | |
359 | ||
360 | assert(s); | |
361 | assert(c); | |
362 | ||
363 | if (!c->delete_self_handler_called) | |
364 | return; | |
365 | ||
366 | for (n = 0; n < 3; n++) { | |
367 | unsigned i; | |
368 | ||
369 | if (c->create_overflow & (1U << n)) | |
370 | continue; | |
371 | ||
372 | for (i = 0; i < c->n_create_events; i++) | |
373 | if (!(c->create_called[i] & (1U << n))) | |
374 | return; | |
375 | } | |
376 | ||
377 | sd_event_exit(sd_event_source_get_event(s), 0); | |
378 | } | |
379 | ||
380 | static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) { | |
381 | struct inotify_context *c = userdata; | |
382 | const char *description; | |
383 | unsigned bit, n; | |
384 | ||
385 | assert_se(sd_event_source_get_description(s, &description) >= 0); | |
386 | assert_se(safe_atou(description, &n) >= 0); | |
387 | ||
388 | assert_se(n <= 3); | |
389 | bit = 1U << n; | |
390 | ||
391 | if (ev->mask & IN_Q_OVERFLOW) { | |
392 | log_info("inotify-handler <%s>: overflow", description); | |
393 | c->create_overflow |= bit; | |
394 | } else if (ev->mask & IN_CREATE) { | |
395 | unsigned i; | |
396 | ||
397 | log_info("inotify-handler <%s>: create on %s", description, ev->name); | |
398 | ||
399 | if (!streq(ev->name, "sub")) { | |
400 | assert_se(safe_atou(ev->name, &i) >= 0); | |
401 | ||
402 | assert_se(i < c->n_create_events); | |
403 | c->create_called[i] |= bit; | |
404 | } | |
405 | } else if (ev->mask & IN_DELETE) { | |
406 | log_info("inotify-handler <%s>: delete of %s", description, ev->name); | |
407 | assert_se(streq(ev->name, "sub")); | |
408 | } else | |
409 | assert_not_reached("unexpected inotify event"); | |
410 | ||
411 | maybe_exit(s, c); | |
412 | return 1; | |
413 | } | |
414 | ||
415 | static int delete_self_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) { | |
416 | struct inotify_context *c = userdata; | |
417 | ||
418 | if (ev->mask & IN_Q_OVERFLOW) { | |
419 | log_info("delete-self-handler: overflow"); | |
420 | c->delete_self_handler_called = true; | |
421 | } else if (ev->mask & IN_DELETE_SELF) { | |
422 | log_info("delete-self-handler: delete-self"); | |
423 | c->delete_self_handler_called = true; | |
424 | } else if (ev->mask & IN_IGNORED) { | |
425 | log_info("delete-self-handler: ignore"); | |
426 | } else | |
427 | assert_not_reached("unexpected inotify event (delete-self)"); | |
428 | ||
429 | maybe_exit(s, c); | |
430 | return 1; | |
431 | } | |
432 | ||
433 | static void test_inotify(unsigned n_create_events) { | |
434 | _cleanup_(rm_rf_physical_and_freep) char *p = NULL; | |
435 | sd_event_source *a = NULL, *b = NULL, *c = NULL, *d = NULL; | |
436 | struct inotify_context context = { | |
437 | .n_create_events = n_create_events, | |
438 | }; | |
439 | sd_event *e = NULL; | |
440 | const char *q; | |
441 | unsigned i; | |
442 | ||
443 | assert_se(sd_event_default(&e) >= 0); | |
444 | ||
445 | assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0); | |
446 | ||
447 | assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0); | |
448 | assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0); | |
449 | assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_IDLE) >= 0); | |
450 | assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_NORMAL) >= 0); | |
451 | assert_se(sd_event_add_inotify(e, &c, p, IN_CREATE|IN_DELETE|IN_EXCL_UNLINK, inotify_handler, &context) >= 0); | |
452 | assert_se(sd_event_source_set_priority(c, SD_EVENT_PRIORITY_IDLE) >= 0); | |
453 | ||
454 | assert_se(sd_event_source_set_description(a, "0") >= 0); | |
455 | assert_se(sd_event_source_set_description(b, "1") >= 0); | |
456 | assert_se(sd_event_source_set_description(c, "2") >= 0); | |
457 | ||
458 | q = strjoina(p, "/sub"); | |
459 | assert_se(touch(q) >= 0); | |
460 | assert_se(sd_event_add_inotify(e, &d, q, IN_DELETE_SELF, delete_self_handler, &context) >= 0); | |
461 | ||
462 | for (i = 0; i < n_create_events; i++) { | |
463 | char buf[DECIMAL_STR_MAX(unsigned)+1]; | |
464 | _cleanup_free_ char *z; | |
465 | ||
466 | xsprintf(buf, "%u", i); | |
467 | assert_se(z = strjoin(p, "/", buf)); | |
468 | ||
469 | assert_se(touch(z) >= 0); | |
470 | } | |
471 | ||
472 | assert_se(unlink(q) >= 0); | |
473 | ||
474 | assert_se(sd_event_loop(e) >= 0); | |
475 | ||
476 | sd_event_source_unref(a); | |
477 | sd_event_source_unref(b); | |
478 | sd_event_source_unref(c); | |
479 | sd_event_source_unref(d); | |
480 | ||
481 | sd_event_unref(e); | |
482 | } | |
483 | ||
9da4cb2b | 484 | int main(int argc, char *argv[]) { |
6d7c4033 | 485 | test_setup_logging(LOG_DEBUG); |
2c86ba5a | 486 | |
9da4cb2b | 487 | test_basic(); |
2c86ba5a | 488 | test_sd_event_now(); |
9da4cb2b | 489 | test_rtqueue(); |
fd38203a | 490 | |
41e09d62 LP |
491 | test_inotify(100); /* should work without overflow */ |
492 | test_inotify(33000); /* should trigger a q overflow */ | |
493 | ||
fd38203a LP |
494 | return 0; |
495 | } |