chiark / gitweb /
bus: add minimal event loop API
[elogind.git] / src / libsystemd-bus / 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
26 static int prepare_handler(sd_event_source *s, void *userdata) {
27         log_info("preparing %c", PTR_TO_INT(userdata));
28         return 1;
29 }
30
31 static bool got_a, got_b, got_c;
32
33 static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
34
35         log_info("got IO on %c", PTR_TO_INT(userdata));
36
37         if (userdata == INT_TO_PTR('a')) {
38                 assert_se(sd_event_source_set_mute(s, SD_EVENT_MUTED) >= 0);
39                 assert_se(!got_a);
40                 got_a = true;
41         } else if (userdata == INT_TO_PTR('b')) {
42                 assert_se(!got_b);
43                 got_b = true;
44         } else
45                 assert_not_reached("Yuck!");
46
47         return 1;
48 }
49
50 static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
51
52         assert(s);
53         assert(si);
54
55         log_info("got child on %c", PTR_TO_INT(userdata));
56
57         assert(userdata == INT_TO_PTR('f'));
58
59         assert_se(sd_event_request_quit(sd_event_get(s)) >= 0);
60         sd_event_source_unref(s);
61
62         return 1;
63 }
64
65 static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
66         sd_event_source *p;
67         sigset_t ss;
68         pid_t pid;
69
70         assert(s);
71         assert(si);
72
73         log_info("got signal on %c", PTR_TO_INT(userdata));
74
75         assert(userdata == INT_TO_PTR('e'));
76
77         assert_se(sigemptyset(&ss) >= 0);
78         assert_se(sigaddset(&ss, SIGCHLD) >= 0);
79         assert_se(sigprocmask(SIG_BLOCK, &ss, NULL) >= 0);
80
81         pid = fork();
82         assert_se(pid >= 0);
83
84         if (pid == 0)
85                 _exit(0);
86
87         assert_se(sd_event_add_child(sd_event_get(s), pid, WEXITED, child_handler, INT_TO_PTR('f'), &p) >= 0);
88         assert_se(sd_event_source_set_mute(p, SD_EVENT_ONESHOT) >= 0);
89
90         sd_event_source_unref(s);
91
92         return 1;
93 }
94
95 static int defer_handler(sd_event_source *s, void *userdata) {
96         sd_event_source *p;
97         sigset_t ss;
98
99         assert(s);
100
101         log_info("got defer on %c", PTR_TO_INT(userdata));
102
103         assert(userdata == INT_TO_PTR('d'));
104
105         assert_se(sigemptyset(&ss) >= 0);
106         assert_se(sigaddset(&ss, SIGUSR1) >= 0);
107         assert_se(sigprocmask(SIG_BLOCK, &ss, NULL) >= 0);
108         assert_se(sd_event_add_signal(sd_event_get(s), SIGUSR1, signal_handler, INT_TO_PTR('e'), &p) >= 0);
109         assert_se(sd_event_source_set_mute(p, SD_EVENT_ONESHOT) >= 0);
110         raise(SIGUSR1);
111
112         sd_event_source_unref(s);
113
114         return 1;
115 }
116
117 static bool do_quit = false;
118
119 static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
120         log_info("got timer on %c", PTR_TO_INT(userdata));
121
122         if (userdata == INT_TO_PTR('c')) {
123
124                 if (do_quit) {
125                         sd_event_source *p;
126
127                         assert_se(sd_event_add_defer(sd_event_get(s), defer_handler, INT_TO_PTR('d'), &p) >= 0);
128                         assert_se(sd_event_source_set_mute(p, SD_EVENT_ONESHOT) >= 0);
129                 } else {
130                         assert(!got_c);
131                         got_c = true;
132                 }
133         } else
134                 assert_not_reached("Huh?");
135
136         return 2;
137 }
138
139 int main(int argc, char *argv[]) {
140         sd_event *e = NULL;
141         sd_event_source *x = NULL, *y = NULL, *z = NULL;
142         static const char ch = 'x';
143         int a[2] = { -1, -1 }, b[2] = { -1, -1};
144
145         assert_se(pipe(a) >= 0);
146         assert_se(pipe(b) >= 0);
147
148         assert_se(sd_event_new(&e) >= 0);
149
150         got_a = false, got_b = false, got_c = false;
151
152         assert_se(sd_event_add_io(e, a[0], EPOLLIN, io_handler, INT_TO_PTR('a'), &x) >= 0);
153         assert_se(sd_event_add_io(e, b[0], EPOLLIN, io_handler, INT_TO_PTR('b'), &y) >= 0);
154         assert_se(sd_event_add_monotonic(e, 0, time_handler, INT_TO_PTR('c'), &z) >= 0);
155
156         assert_se(sd_event_source_set_priority(x, 99) >= 0);
157         assert_se(sd_event_source_set_mute(y, SD_EVENT_ONESHOT) >= 0);
158         assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0);
159         assert_se(sd_event_source_set_priority(z, 50) >= 0);
160         assert_se(sd_event_source_set_mute(z, SD_EVENT_ONESHOT) >= 0);
161         assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
162
163         assert_se(write(a[1], &ch, 1) >= 0);
164         assert_se(write(b[1], &ch, 1) >= 0);
165
166         assert_se(!got_a && !got_b && !got_c);
167
168         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
169
170         assert_se(!got_a && got_b && !got_c);
171
172         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
173
174         assert_se(!got_a && got_b && got_c);
175
176         assert_se(sd_event_run(e, (uint64_t) -1) >= 1);
177
178         assert_se(got_a && got_b && got_c);
179
180         sd_event_source_unref(x);
181         sd_event_source_unref(y);
182
183         do_quit = true;
184         assert_se(sd_event_source_set_time(z, now(CLOCK_MONOTONIC) + 200 * USEC_PER_MSEC) >= 0);
185         assert_se(sd_event_source_set_mute(z, SD_EVENT_ONESHOT) >= 0);
186
187         assert_se(sd_event_loop(e) >= 0);
188
189         sd_event_source_unref(z);
190
191         sd_event_unref(e);
192
193         close_pipe(a);
194         close_pipe(b);
195
196         return 0;
197 }