1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "signal-util.h"
30 /// Additional includes needed by elogind
31 #include "process-util.h"
33 static int prepare_handler(sd_event_source *s, void *userdata) {
34 log_info("preparing %c", PTR_TO_INT(userdata));
38 static bool got_a, got_b, got_c, got_unref;
39 static unsigned got_d;
41 static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
42 sd_event_source_unref(s);
47 static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
49 log_info("got IO on %c", PTR_TO_INT(userdata));
51 if (userdata == INT_TO_PTR('a')) {
52 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
55 } else if (userdata == INT_TO_PTR('b')) {
58 } else if (userdata == INT_TO_PTR('d')) {
61 assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0);
63 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
65 assert_not_reached("Yuck!");
70 static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
75 log_info("got child on %c", PTR_TO_INT(userdata));
77 assert_se(userdata == INT_TO_PTR('f'));
79 assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
80 sd_event_source_unref(s);
85 static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
86 sd_event_source *p = NULL;
92 log_info("got signal on %c", PTR_TO_INT(userdata));
94 assert_se(userdata == INT_TO_PTR('e'));
96 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
104 assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
105 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
107 sd_event_source_unref(s);
112 static int defer_handler(sd_event_source *s, void *userdata) {
113 sd_event_source *p = NULL;
117 log_info("got defer on %c", PTR_TO_INT(userdata));
119 assert_se(userdata == INT_TO_PTR('d'));
121 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0);
123 assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
124 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
127 sd_event_source_unref(s);
132 static bool do_quit = false;
134 static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
135 log_info("got timer on %c", PTR_TO_INT(userdata));
137 if (userdata == INT_TO_PTR('c')) {
142 assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0);
143 assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
149 assert_not_reached("Huh?");
154 static bool got_exit = false;
156 static int exit_handler(sd_event_source *s, void *userdata) {
157 log_info("got quit handler on %c", PTR_TO_INT(userdata));
164 static bool got_post = false;
166 static int post_handler(sd_event_source *s, void *userdata) {
167 log_info("got post handler");
174 static void test_basic(void) {
176 sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL;
177 static const char ch = 'x';
178 int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 };
182 assert_se(pipe(a) >= 0);
183 assert_se(pipe(b) >= 0);
184 assert_se(pipe(d) >= 0);
185 assert_se(pipe(k) >= 0);
187 assert_se(sd_event_default(&e) >= 0);
188 assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
190 assert_se(sd_event_set_watchdog(e, true) >= 0);
192 /* Test whether we cleanly can destroy an io event source from its own handler */
194 assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0);
195 assert_se(write(k[1], &ch, 1) == 1);
196 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
197 assert_se(got_unref);
199 got_a = false, got_b = false, got_c = false, got_d = 0;
201 /* Add a oneshot handler, trigger it, re-enable it, and trigger
203 assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
204 assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
205 assert_se(write(d[1], &ch, 1) >= 0);
206 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
207 assert_se(got_d == 1);
208 assert_se(write(d[1], &ch, 1) >= 0);
209 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
210 assert_se(got_d == 2);
212 assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0);
213 assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0);
214 assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0);
215 assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0);
217 assert_se(sd_event_source_set_priority(x, 99) >= 0);
218 assert_se(sd_event_source_get_priority(x, &priority) >= 0);
219 assert_se(priority == 99);
220 assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0);
221 assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0);
222 assert_se(sd_event_source_set_priority(z, 50) >= 0);
223 assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
224 assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
226 /* Test for floating event sources */
227 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1, -1) >= 0);
228 assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
230 assert_se(write(a[1], &ch, 1) >= 0);
231 assert_se(write(b[1], &ch, 1) >= 0);
233 assert_se(!got_a && !got_b && !got_c);
235 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
237 assert_se(!got_a && got_b && !got_c);
239 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
241 assert_se(!got_a && got_b && got_c);
243 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
245 assert_se(got_a && got_b && got_c);
247 sd_event_source_unref(x);
248 sd_event_source_unref(y);
251 assert_se(sd_event_add_post(e, NULL, post_handler, NULL) >= 0);
252 assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
253 assert_se(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC) >= 0);
254 assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
256 assert_se(sd_event_loop(e) >= 0);
260 sd_event_source_unref(z);
261 sd_event_source_unref(q);
263 sd_event_source_unref(w);
273 static void test_sd_event_now(void) {
274 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
277 assert_se(sd_event_new(&e) >= 0);
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);
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);
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);
288 assert_se(sd_event_run(e, 0) == 0);
290 assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
291 assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) == 0);
292 assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) == 0);
293 if (clock_boottime_supported()) {
294 assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0);
295 assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0);
297 assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
298 assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
301 static int last_rtqueue_sigval = 0;
302 static int n_rtqueue = 0;
304 static int rtqueue_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
305 last_rtqueue_sigval = si->ssi_int;
310 static void test_rtqueue(void) {
311 sd_event_source *u = NULL, *v = NULL, *s = NULL;
314 assert_se(sd_event_default(&e) >= 0);
316 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0);
317 assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0);
318 assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0);
319 assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0);
321 assert_se(sd_event_source_set_priority(v, -10) >= 0);
323 assert_se(sigqueue(getpid_cached(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0);
324 assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0);
325 assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0);
326 assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0);
327 assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0);
329 assert_se(n_rtqueue == 0);
330 assert_se(last_rtqueue_sigval == 0);
332 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
333 assert_se(n_rtqueue == 1);
334 assert_se(last_rtqueue_sigval == 2); /* first SIGRTMIN+3 */
336 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
337 assert_se(n_rtqueue == 2);
338 assert_se(last_rtqueue_sigval == 4); /* second SIGRTMIN+3 */
340 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
341 assert_se(n_rtqueue == 3);
342 assert_se(last_rtqueue_sigval == 3); /* first SIGUSR2 */
344 assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
345 assert_se(n_rtqueue == 4);
346 assert_se(last_rtqueue_sigval == 1); /* SIGRTMIN+2 */
348 assert_se(sd_event_run(e, 0) == 0); /* the other SIGUSR2 is dropped, because the first one was still queued */
349 assert_se(n_rtqueue == 4);
350 assert_se(last_rtqueue_sigval == 1);
352 sd_event_source_unref(u);
353 sd_event_source_unref(v);
354 sd_event_source_unref(s);
359 int main(int argc, char *argv[]) {
361 log_set_max_level(LOG_DEBUG);
362 log_parse_environment();