chiark / gitweb /
pam_elogind compiling
[elogind.git] / src / libsystemd / sd-event / test-event.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "sd-event.h"
23 #include "log.h"
24 #include "util.h"
25 #include "macro.h"
26
27 static int prepare_handler(sd_event_source *s, void *userdata) {
28         log_info("preparing %c", PTR_TO_INT(userdata));
29         return 1;
30 }
31
32 static bool got_a, got_b, got_c, got_unref;
33 static unsigned got_d;
34
35 static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
36         sd_event_source_unref(s);
37         got_unref = true;
38         return 0;
39 }
40
41 static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
42
43         log_info("got IO on %c", PTR_TO_INT(userdata));
44
45         if (userdata == INT_TO_PTR('a')) {
46                 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
47                 assert_se(!got_a);
48                 got_a = true;
49         } else if (userdata == INT_TO_PTR('b')) {
50                 assert_se(!got_b);
51                 got_b = true;
52         } else if (userdata == INT_TO_PTR('d')) {
53                 got_d++;
54                 if (got_d < 2)
55                         assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0);
56                 else
57                         assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
58         } else
59                 assert_not_reached("Yuck!");
60
61         return 1;
62 }
63
64 static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
65
66         assert_se(s);
67         assert_se(si);
68
69         log_info("got child on %c", PTR_TO_INT(userdata));
70
71         assert_se(userdata == INT_TO_PTR('f'));
72
73         assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
74         sd_event_source_unref(s);
75
76         return 1;
77 }
78
79 static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
80         sd_event_source *p = NULL;
81         sigset_t ss;
82         pid_t pid;
83
84         assert_se(s);
85         assert_se(si);
86
87         log_info("got signal on %c", PTR_TO_INT(userdata));
88
89         assert_se(userdata == INT_TO_PTR('e'));
90
91         assert_se(sigemptyset(&ss) >= 0);
92         assert_se(sigaddset(&ss, SIGCHLD) >= 0);
93         assert_se(sigprocmask(SIG_BLOCK, &ss, NULL) >= 0);
94
95         pid = fork();
96         assert_se(pid >= 0);
97
98         if (pid == 0)
99                 _exit(0);
100
101         assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
102         assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
103
104         sd_event_source_unref(s);
105
106         return 1;
107 }
108
109 static int defer_handler(sd_event_source *s, void *userdata) {
110         sd_event_source *p = NULL;
111         sigset_t ss;
112
113         assert_se(s);
114
115         log_info("got defer on %c", PTR_TO_INT(userdata));
116
117         assert_se(userdata == INT_TO_PTR('d'));
118
119         assert_se(sigemptyset(&ss) >= 0);
120         assert_se(sigaddset(&ss, SIGUSR1) >= 0);
121         assert_se(sigprocmask(SIG_BLOCK, &ss, NULL) >= 0);
122         assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
123         assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
124         raise(SIGUSR1);
125
126         sd_event_source_unref(s);
127
128         return 1;
129 }
130
131 static bool do_quit = false;
132
133 static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
134         log_info("got timer on %c", PTR_TO_INT(userdata));
135
136         if (userdata == INT_TO_PTR('c')) {
137
138                 if (do_quit) {
139                         sd_event_source *p;
140
141                         assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0);
142                         assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
143                 } else {
144                         assert_se(!got_c);
145                         got_c = true;
146                 }
147         } else
148                 assert_not_reached("Huh?");
149
150         return 2;
151 }
152
153 static bool got_exit = false;
154
155 static int exit_handler(sd_event_source *s, void *userdata) {
156         log_info("got quit handler on %c", PTR_TO_INT(userdata));
157
158         got_exit = true;
159
160         return 3;
161 }
162
163 int main(int argc, char *argv[]) {
164         sd_event *e = NULL;
165         sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL;
166         static const char ch = 'x';
167         int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 };
168
169         assert_se(pipe(a) >= 0);
170         assert_se(pipe(b) >= 0);
171         assert_se(pipe(d) >= 0);
172         assert_se(pipe(k) >= 0);
173
174         assert_se(sd_event_default(&e) >= 0);
175
176         assert_se(sd_event_set_watchdog(e, true) >= 0);
177
178         /* Test whether we cleanly can destroy an io event source from its own handler */
179         got_unref = false;
180         assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0);
181         assert_se(write(k[1], &ch, 1) == 1);
182         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
183         assert_se(got_unref);
184
185         got_a = false, got_b = false, got_c = false, got_d = 0;
186
187         /* Add a oneshot handler, trigger it, re-enable it, and trigger
188          * it again. */
189         assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
190         assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
191         assert_se(write(d[1], &ch, 1) >= 0);
192         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
193         assert_se(got_d == 1);
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 == 2);
197
198         assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0);
199         assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0);
200         assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0);
201         assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0);
202
203         assert_se(sd_event_source_set_priority(x, 99) >= 0);
204         assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0);
205         assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0);
206         assert_se(sd_event_source_set_priority(z, 50) >= 0);
207         assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
208         assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
209
210         /* Test for floating event sources */
211         assert_se(sigprocmask_many(SIG_BLOCK, SIGRTMIN+1, -1) == 0);
212         assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
213
214         assert_se(write(a[1], &ch, 1) >= 0);
215         assert_se(write(b[1], &ch, 1) >= 0);
216
217         assert_se(!got_a && !got_b && !got_c);
218
219         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
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         sd_event_source_unref(x);
232         sd_event_source_unref(y);
233
234         do_quit = true;
235         assert_se(sd_event_source_set_time(z, now(CLOCK_MONOTONIC) + 200 * USEC_PER_MSEC) >= 0);
236         assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
237
238         assert_se(sd_event_loop(e) >= 0);
239
240         sd_event_source_unref(z);
241         sd_event_source_unref(q);
242
243         sd_event_source_unref(w);
244
245         sd_event_unref(e);
246
247         safe_close_pair(a);
248         safe_close_pair(b);
249         safe_close_pair(d);
250         safe_close_pair(k);
251
252         return 0;
253 }