chiark / gitweb /
Unifiy free() usage
[elogind.git] / src / libelogind / 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 #include "signal-util.h"
27
28 static int prepare_handler(sd_event_source *s, void *userdata) {
29         log_info("preparing %c", PTR_TO_INT(userdata));
30         return 1;
31 }
32
33 static bool got_a, got_b, got_c, got_unref;
34 static unsigned got_d;
35
36 static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
37         sd_event_source_unref(s);
38         got_unref = true;
39         return 0;
40 }
41
42 static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
43
44         log_info("got IO on %c", PTR_TO_INT(userdata));
45
46         if (userdata == INT_TO_PTR('a')) {
47                 assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
48                 assert_se(!got_a);
49                 got_a = true;
50         } else if (userdata == INT_TO_PTR('b')) {
51                 assert_se(!got_b);
52                 got_b = true;
53         } else if (userdata == INT_TO_PTR('d')) {
54                 got_d++;
55                 if (got_d < 2)
56                         assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0);
57                 else
58                         assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
59         } else
60                 assert_not_reached("Yuck!");
61
62         return 1;
63 }
64
65 static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
66
67         assert_se(s);
68         assert_se(si);
69
70         log_info("got child on %c", PTR_TO_INT(userdata));
71
72         assert_se(userdata == INT_TO_PTR('f'));
73
74         assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
75         sd_event_source_unref(s);
76
77         return 1;
78 }
79
80 static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
81         sd_event_source *p = NULL;
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(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
92
93         pid = fork();
94         assert_se(pid >= 0);
95
96         if (pid == 0)
97                 _exit(0);
98
99         assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
100         assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
101
102         sd_event_source_unref(s);
103
104         return 1;
105 }
106
107 static int defer_handler(sd_event_source *s, void *userdata) {
108         sd_event_source *p = NULL;
109
110         assert_se(s);
111
112         log_info("got defer on %c", PTR_TO_INT(userdata));
113
114         assert_se(userdata == INT_TO_PTR('d'));
115
116         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0);
117
118         assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
119         assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
120         raise(SIGUSR1);
121
122         sd_event_source_unref(s);
123
124         return 1;
125 }
126
127 static bool do_quit = false;
128
129 static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
130         log_info("got timer on %c", PTR_TO_INT(userdata));
131
132         if (userdata == INT_TO_PTR('c')) {
133
134                 if (do_quit) {
135                         sd_event_source *p;
136
137                         assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0);
138                         assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
139                 } else {
140                         assert_se(!got_c);
141                         got_c = true;
142                 }
143         } else
144                 assert_not_reached("Huh?");
145
146         return 2;
147 }
148
149 static bool got_exit = false;
150
151 static int exit_handler(sd_event_source *s, void *userdata) {
152         log_info("got quit handler on %c", PTR_TO_INT(userdata));
153
154         got_exit = true;
155
156         return 3;
157 }
158
159 int main(int argc, char *argv[]) {
160         sd_event *e = NULL;
161         sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL;
162         static const char ch = 'x';
163         int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 };
164
165         assert_se(pipe(a) >= 0);
166         assert_se(pipe(b) >= 0);
167         assert_se(pipe(d) >= 0);
168         assert_se(pipe(k) >= 0);
169
170         assert_se(sd_event_default(&e) >= 0);
171
172         assert_se(sd_event_set_watchdog(e, true) >= 0);
173
174         /* Test whether we cleanly can destroy an io event source from its own handler */
175         got_unref = false;
176         assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0);
177         assert_se(write(k[1], &ch, 1) == 1);
178         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
179         assert_se(got_unref);
180
181         got_a = false, got_b = false, got_c = false, got_d = 0;
182
183         /* Add a oneshot handler, trigger it, re-enable it, and trigger
184          * it again. */
185         assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
186         assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
187         assert_se(write(d[1], &ch, 1) >= 0);
188         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
189         assert_se(got_d == 1);
190         assert_se(write(d[1], &ch, 1) >= 0);
191         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
192         assert_se(got_d == 2);
193
194         assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0);
195         assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0);
196         assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0);
197         assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0);
198
199         assert_se(sd_event_source_set_priority(x, 99) >= 0);
200         assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0);
201         assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0);
202         assert_se(sd_event_source_set_priority(z, 50) >= 0);
203         assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
204         assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
205
206         /* Test for floating event sources */
207         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1, -1) >= 0);
208         assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
209
210         assert_se(write(a[1], &ch, 1) >= 0);
211         assert_se(write(b[1], &ch, 1) >= 0);
212
213         assert_se(!got_a && !got_b && !got_c);
214
215         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
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         sd_event_source_unref(x);
228         sd_event_source_unref(y);
229
230         do_quit = true;
231         assert_se(sd_event_source_set_time(z, now(CLOCK_MONOTONIC) + 200 * USEC_PER_MSEC) >= 0);
232         assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
233
234         assert_se(sd_event_loop(e) >= 0);
235
236         sd_event_source_unref(z);
237         sd_event_source_unref(q);
238
239         sd_event_source_unref(w);
240
241         sd_event_unref(e);
242
243         safe_close_pair(a);
244         safe_close_pair(b);
245         safe_close_pair(d);
246         safe_close_pair(k);
247
248         return 0;
249 }