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