1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
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.
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.
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/>.
24 * These tests verify the correct behavior of the IPC Barrier implementation.
25 * Note that the tests use alarm-timers to verify dead-locks and timeouts. These
26 * might not work on slow machines where 20ms are too short to perform specific
27 * operations (though, very unlikely). In case that turns out true, we have to
28 * increase it at the slightly cost of lengthen test-duration on other machines.
39 /* 20ms to test deadlocks; All timings use multiples of this constant as
40 * alarm/sleep timers. If this timeout is too small for slow machines to perform
41 * the requested operations, we have to increase it. On an i7 this works fine
42 * with 1ms base-time, so 20ms should be just fine for everyone. */
43 #define BASE_TIME (20 * USEC_PER_MSEC)
45 static void set_alarm(usec_t usecs) {
46 struct itimerval v = { };
48 timeval_store(&v.it_value, usecs);
49 assert_se(setitimer(ITIMER_REAL, &v, NULL) >= 0);
52 static void sleep_for(usec_t usecs) {
53 /* stupid usleep() might fail if >1000000 */
54 assert_se(usecs < USEC_PER_SEC);
58 #define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \
59 static void _FUNCTION(void) { \
60 Barrier b = BARRIER_NULL; \
63 assert_se(barrier_create(&b) >= 0); \
64 assert_se(b.me > 0); \
65 assert_se(b.them > 0); \
66 assert_se(b.pipe[0] > 0); \
67 assert_se(b.pipe[1] > 0); \
70 assert_se(pid1 >= 0); \
72 barrier_set_role(&b, BARRIER_CHILD); \
78 assert_se(pid2 >= 0); \
80 barrier_set_role(&b, BARRIER_PARENT); \
85 barrier_destroy(&b); \
92 #define TEST_BARRIER_WAIT_SUCCESS(_pid) \
95 pidr = waitpid(_pid, &status, 0); \
96 assert_se(pidr == _pid); \
97 assert_se(WIFEXITED(status)); \
98 assert_se(WEXITSTATUS(status) == 42); \
101 #define TEST_BARRIER_WAIT_ALARM(_pid) \
104 pidr = waitpid(_pid, &status, 0); \
105 assert_se(pidr == _pid); \
106 assert_se(WIFSIGNALED(status)); \
107 assert_se(WTERMSIG(status) == SIGALRM); \
111 * Test basic sync points
112 * This places a barrier in both processes and waits synchronously for them.
113 * The timeout makes sure the sync works as expected. The sleep_for() on one side
114 * makes sure the exit of the parent does not overwrite previous barriers. Due
115 * to the sleep_for(), we know that the parent already exited, thus there's a
116 * pending HUP on the pipe. However, the barrier_sync() prefers reads on the
117 * eventfd, thus we can safely wait on the barrier.
119 TEST_BARRIER(test_barrier_sync,
121 set_alarm(BASE_TIME * 10);
122 assert_se(barrier_place(&b));
123 sleep_for(BASE_TIME * 2);
124 assert_se(barrier_sync(&b));
126 TEST_BARRIER_WAIT_SUCCESS(pid1),
128 set_alarm(BASE_TIME * 10);
129 assert_se(barrier_place(&b));
130 assert_se(barrier_sync(&b));
132 TEST_BARRIER_WAIT_SUCCESS(pid2));
136 * This places a barrier in the parent and syncs on it. The child sleeps while
137 * the parent places the barrier and then waits for a barrier. The wait will
138 * succeed as the child hasn't read the parent's barrier, yet. The following
139 * barrier and sync synchronize the exit.
141 TEST_BARRIER(test_barrier_wait_next,
143 sleep_for(BASE_TIME);
144 set_alarm(BASE_TIME * 10);
145 assert_se(barrier_wait_next(&b));
146 assert_se(barrier_place(&b));
147 assert_se(barrier_sync(&b));
149 TEST_BARRIER_WAIT_SUCCESS(pid1),
151 set_alarm(BASE_TIME * 4);
152 assert_se(barrier_place(&b));
153 assert_se(barrier_sync(&b));
155 TEST_BARRIER_WAIT_SUCCESS(pid2));
158 * Test wait_next() multiple times
159 * This places two barriers in the parent and waits for the child to exit. The
160 * child sleeps 20ms so both barriers _should_ be in place. It then waits for
161 * the parent to place the next barrier twice. The first call will fetch both
162 * barriers and return. However, the second call will stall as the parent does
163 * not place a 3rd barrier (the sleep caught two barriers). wait_next() is does
164 * not look at barrier-links so this stall is expected. Thus this test times
167 TEST_BARRIER(test_barrier_wait_next_twice,
169 sleep_for(BASE_TIME);
170 set_alarm(BASE_TIME);
171 assert_se(barrier_wait_next(&b));
172 assert_se(barrier_wait_next(&b));
175 TEST_BARRIER_WAIT_ALARM(pid1),
177 set_alarm(BASE_TIME * 10);
178 assert_se(barrier_place(&b));
179 assert_se(barrier_place(&b));
180 sleep_for(BASE_TIME * 4);
182 TEST_BARRIER_WAIT_SUCCESS(pid2));
185 * Test wait_next() with local barriers
186 * This is the same as test_barrier_wait_next_twice, but places local barriers
187 * between both waits. This does not have any effect on the wait so it times out
188 * like the other test.
190 TEST_BARRIER(test_barrier_wait_next_twice_local,
192 sleep_for(BASE_TIME);
193 set_alarm(BASE_TIME);
194 assert_se(barrier_wait_next(&b));
195 assert_se(barrier_place(&b));
196 assert_se(barrier_place(&b));
197 assert_se(barrier_wait_next(&b));
200 TEST_BARRIER_WAIT_ALARM(pid1),
202 set_alarm(BASE_TIME * 10);
203 assert_se(barrier_place(&b));
204 assert_se(barrier_place(&b));
205 sleep_for(BASE_TIME * 4);
207 TEST_BARRIER_WAIT_SUCCESS(pid2));
210 * Test wait_next() with sync_next()
211 * This is again the same as test_barrier_wait_next_twice but uses a
212 * synced wait as the second wait. This works just fine because the local state
213 * has no barriers placed, therefore, the remote is always in sync.
215 TEST_BARRIER(test_barrier_wait_next_twice_sync,
217 sleep_for(BASE_TIME);
218 set_alarm(BASE_TIME);
219 assert_se(barrier_wait_next(&b));
220 assert_se(barrier_sync_next(&b));
222 TEST_BARRIER_WAIT_SUCCESS(pid1),
224 set_alarm(BASE_TIME * 10);
225 assert_se(barrier_place(&b));
226 assert_se(barrier_place(&b));
228 TEST_BARRIER_WAIT_SUCCESS(pid2));
231 * Test wait_next() with sync_next() and local barriers
232 * This is again the same as test_barrier_wait_next_twice_local but uses a
233 * synced wait as the second wait. This works just fine because the local state
234 * is in sync with the remote.
236 TEST_BARRIER(test_barrier_wait_next_twice_local_sync,
238 sleep_for(BASE_TIME);
239 set_alarm(BASE_TIME);
240 assert_se(barrier_wait_next(&b));
241 assert_se(barrier_place(&b));
242 assert_se(barrier_place(&b));
243 assert_se(barrier_sync_next(&b));
245 TEST_BARRIER_WAIT_SUCCESS(pid1),
247 set_alarm(BASE_TIME * 10);
248 assert_se(barrier_place(&b));
249 assert_se(barrier_place(&b));
251 TEST_BARRIER_WAIT_SUCCESS(pid2));
254 * Test sync_next() and sync()
255 * This tests sync_*() synchronizations and makes sure they work fine if the
256 * local state is behind the remote state.
258 TEST_BARRIER(test_barrier_sync_next,
260 set_alarm(BASE_TIME * 10);
261 assert_se(barrier_sync_next(&b));
262 assert_se(barrier_sync(&b));
263 assert_se(barrier_place(&b));
264 assert_se(barrier_place(&b));
265 assert_se(barrier_sync_next(&b));
266 assert_se(barrier_sync_next(&b));
267 assert_se(barrier_sync(&b));
269 TEST_BARRIER_WAIT_SUCCESS(pid1),
271 set_alarm(BASE_TIME * 10);
272 sleep_for(BASE_TIME);
273 assert_se(barrier_place(&b));
274 assert_se(barrier_place(&b));
275 assert_se(barrier_sync(&b));
277 TEST_BARRIER_WAIT_SUCCESS(pid2));
280 * Test sync_next() and sync() with local barriers
281 * This tests timeouts if sync_*() is used if local barriers are placed but the
282 * remote didn't place any.
284 TEST_BARRIER(test_barrier_sync_next_local,
286 set_alarm(BASE_TIME);
287 assert_se(barrier_place(&b));
288 assert_se(barrier_sync_next(&b));
291 TEST_BARRIER_WAIT_ALARM(pid1),
293 sleep_for(BASE_TIME * 2);
295 TEST_BARRIER_WAIT_SUCCESS(pid2));
298 * Test sync_next() and sync() with local barriers and abortion
299 * This is the same as test_barrier_sync_next_local but aborts the sync in the
300 * parent. Therefore, the sync_next() succeeds just fine due to the abortion.
302 TEST_BARRIER(test_barrier_sync_next_local_abort,
304 set_alarm(BASE_TIME * 10);
305 assert_se(barrier_place(&b));
306 assert_se(!barrier_sync_next(&b));
308 TEST_BARRIER_WAIT_SUCCESS(pid1),
310 assert_se(barrier_abort(&b));
312 TEST_BARRIER_WAIT_SUCCESS(pid2));
315 * Test matched wait_abortion()
316 * This runs wait_abortion() with remote abortion.
318 TEST_BARRIER(test_barrier_wait_abortion,
320 set_alarm(BASE_TIME * 10);
321 assert_se(barrier_wait_abortion(&b));
323 TEST_BARRIER_WAIT_SUCCESS(pid1),
325 assert_se(barrier_abort(&b));
327 TEST_BARRIER_WAIT_SUCCESS(pid2));
330 * Test unmatched wait_abortion()
331 * This runs wait_abortion() without any remote abortion going on. It thus must
334 TEST_BARRIER(test_barrier_wait_abortion_unmatched,
336 set_alarm(BASE_TIME);
337 assert_se(barrier_wait_abortion(&b));
340 TEST_BARRIER_WAIT_ALARM(pid1),
342 sleep_for(BASE_TIME * 2);
344 TEST_BARRIER_WAIT_SUCCESS(pid2));
347 * Test matched wait_abortion() with local abortion
348 * This runs wait_abortion() with local and remote abortion.
350 TEST_BARRIER(test_barrier_wait_abortion_local,
352 set_alarm(BASE_TIME * 10);
353 assert_se(barrier_abort(&b));
354 assert_se(!barrier_wait_abortion(&b));
356 TEST_BARRIER_WAIT_SUCCESS(pid1),
358 assert_se(barrier_abort(&b));
360 TEST_BARRIER_WAIT_SUCCESS(pid2));
363 * Test unmatched wait_abortion() with local abortion
364 * This runs wait_abortion() with only local abortion. This must time out.
366 TEST_BARRIER(test_barrier_wait_abortion_local_unmatched,
368 set_alarm(BASE_TIME);
369 assert_se(barrier_abort(&b));
370 assert_se(!barrier_wait_abortion(&b));
373 TEST_BARRIER_WAIT_ALARM(pid1),
375 sleep_for(BASE_TIME * 2);
377 TEST_BARRIER_WAIT_SUCCESS(pid2));
381 * Place barrier and sync with the child. The child only exits()s, which should
382 * cause an implicit abortion and wake the parent.
384 TEST_BARRIER(test_barrier_exit,
387 TEST_BARRIER_WAIT_SUCCESS(pid1),
389 set_alarm(BASE_TIME * 10);
390 assert_se(barrier_place(&b));
391 assert_se(!barrier_sync(&b));
393 TEST_BARRIER_WAIT_SUCCESS(pid2));
396 * Test child exit with sleep
397 * Same as test_barrier_exit but verifies the test really works due to the
398 * child-exit. We add a usleep() which triggers the alarm in the parent and
399 * causes the test to time out.
401 TEST_BARRIER(test_barrier_no_exit,
403 sleep_for(BASE_TIME * 2);
405 TEST_BARRIER_WAIT_SUCCESS(pid1),
407 set_alarm(BASE_TIME);
408 assert_se(barrier_place(&b));
409 assert_se(!barrier_sync(&b));
411 TEST_BARRIER_WAIT_ALARM(pid2));
414 * Test pending exit against sync
415 * The parent places a barrier *and* exits. The 20ms wait in the child
416 * guarantees both are pending. However, our logic prefers pending barriers over
417 * pending exit-abortions (unlike normal abortions), thus the wait_next() must
418 * succeed, same for the sync_next() as our local barrier-count is smaller than
419 * the remote. Once we place a barrier our count is equal, so the sync still
420 * succeeds. Only if we place one more barrier, we're ahead of the remote, thus
421 * we will fail due to HUP on the pipe.
423 TEST_BARRIER(test_barrier_pending_exit,
425 set_alarm(BASE_TIME * 4);
426 sleep_for(BASE_TIME * 2);
427 assert_se(barrier_wait_next(&b));
428 assert_se(barrier_sync_next(&b));
429 assert_se(barrier_place(&b));
430 assert_se(barrier_sync_next(&b));
431 assert_se(barrier_place(&b));
432 assert_se(!barrier_sync_next(&b));
434 TEST_BARRIER_WAIT_SUCCESS(pid1),
436 assert_se(barrier_place(&b));
438 TEST_BARRIER_WAIT_SUCCESS(pid2));
440 int main(int argc, char *argv[]) {
441 log_parse_environment();
445 test_barrier_wait_next();
446 test_barrier_wait_next_twice();
447 test_barrier_wait_next_twice_sync();
448 test_barrier_wait_next_twice_local();
449 test_barrier_wait_next_twice_local_sync();
450 test_barrier_sync_next();
451 test_barrier_sync_next_local();
452 test_barrier_sync_next_local_abort();
453 test_barrier_wait_abortion();
454 test_barrier_wait_abortion_unmatched();
455 test_barrier_wait_abortion_local();
456 test_barrier_wait_abortion_local_unmatched();
458 test_barrier_no_exit();
459 test_barrier_pending_exit();