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