279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann This file is part of systemd.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann systemd is free software; you can redistribute it and/or modify it
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann under the terms of the GNU Lesser General Public License as published by
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann the Free Software Foundation; either version 2.1 of the License, or
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann (at your option) any later version.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann systemd is distributed in the hope that it will be useful, but
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann WITHOUT ANY WARRANTY; without even the implied warranty of
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann Lesser General Public License for more details.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann You should have received a copy of the GNU Lesser General Public License
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann along with systemd; If not, see <http://www.gnu.org/licenses/>.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * IPC barrier tests
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * These tests verify the correct behavior of the IPC Barrier implementation.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Note that the tests use alarm-timers to verify dead-locks and timeouts. These
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * might not work on slow machines where 20ms are too short to perform specific
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * operations (though, very unlikely). In case that turns out true, we have to
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * increase it at the slightly cost of lengthen test-duration on other machines.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann/* 20ms to test deadlocks; All timings use multiples of this constant as
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * alarm/sleep timers. If this timeout is too small for slow machines to perform
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * the requested operations, we have to increase it. On an i7 this works fine
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * with 1ms base-time, so 20ms should be just fine for everyone. */
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann struct itimerval v = { };
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann assert_se(setitimer(ITIMER_REAL, &v, NULL) >= 0);
cf347234ae78630dd4aad8907f027965e7fb9040David Herrmann /* stupid usleep() might fail if >1000000 */
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann#define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann static void _FUNCTION(void) { \
7566e26721ee95d6fc864e9e6654fb61bd3cd603Zbigniew Jędrzejewski-Szmek assert_se(barrier_create(&b) >= 0); \
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann if (pid1 == 0) { \
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann if (pid2 == 0) { \
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test basic sync points
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This places a barrier in both processes and waits synchronously for them.
cf347234ae78630dd4aad8907f027965e7fb9040David Herrmann * The timeout makes sure the sync works as expected. The sleep_for() on one side
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * makes sure the exit of the parent does not overwrite previous barriers. Due
cf347234ae78630dd4aad8907f027965e7fb9040David Herrmann * to the sleep_for(), we know that the parent already exited, thus there's a
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * pending HUP on the pipe. However, the barrier_sync() prefers reads on the
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * eventfd, thus we can safely wait on the barrier.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test wait_next()
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This places a barrier in the parent and syncs on it. The child sleeps while
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * the parent places the barrier and then waits for a barrier. The wait will
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * succeed as the child hasn't read the parent's barrier, yet. The following
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * barrier and sync synchronize the exit.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test wait_next() multiple times
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This places two barriers in the parent and waits for the child to exit. The
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * child sleeps 20ms so both barriers _should_ be in place. It then waits for
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * the parent to place the next barrier twice. The first call will fetch both
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * barriers and return. However, the second call will stall as the parent does
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * not place a 3rd barrier (the sleep caught two barriers). wait_next() is does
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * not look at barrier-links so this stall is expected. Thus this test times
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test wait_next() with local barriers
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This is the same as test_barrier_wait_next_twice, but places local barriers
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * between both waits. This does not have any effect on the wait so it times out
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * like the other test.
279da1e3f99b9c767a69849b5445e3cfd8d83376David HerrmannTEST_BARRIER(test_barrier_wait_next_twice_local,
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test wait_next() with sync_next()
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This is again the same as test_barrier_wait_next_twice but uses a
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * synced wait as the second wait. This works just fine because the local state
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * has no barriers placed, therefore, the remote is always in sync.
279da1e3f99b9c767a69849b5445e3cfd8d83376David HerrmannTEST_BARRIER(test_barrier_wait_next_twice_sync,
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test wait_next() with sync_next() and local barriers
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This is again the same as test_barrier_wait_next_twice_local but uses a
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * synced wait as the second wait. This works just fine because the local state
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * is in sync with the remote.
279da1e3f99b9c767a69849b5445e3cfd8d83376David HerrmannTEST_BARRIER(test_barrier_wait_next_twice_local_sync,
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test sync_next() and sync()
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This tests sync_*() synchronizations and makes sure they work fine if the
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * local state is behind the remote state.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test sync_next() and sync() with local barriers
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This tests timeouts if sync_*() is used if local barriers are placed but the
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * remote didn't place any.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test sync_next() and sync() with local barriers and abortion
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This is the same as test_barrier_sync_next_local but aborts the sync in the
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * parent. Therefore, the sync_next() succeeds just fine due to the abortion.
279da1e3f99b9c767a69849b5445e3cfd8d83376David HerrmannTEST_BARRIER(test_barrier_sync_next_local_abort,
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test matched wait_abortion()
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This runs wait_abortion() with remote abortion.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test unmatched wait_abortion()
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This runs wait_abortion() without any remote abortion going on. It thus must
279da1e3f99b9c767a69849b5445e3cfd8d83376David HerrmannTEST_BARRIER(test_barrier_wait_abortion_unmatched,
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test matched wait_abortion() with local abortion
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This runs wait_abortion() with local and remote abortion.
279da1e3f99b9c767a69849b5445e3cfd8d83376David HerrmannTEST_BARRIER(test_barrier_wait_abortion_local,
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test unmatched wait_abortion() with local abortion
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * This runs wait_abortion() with only local abortion. This must time out.
279da1e3f99b9c767a69849b5445e3cfd8d83376David HerrmannTEST_BARRIER(test_barrier_wait_abortion_local_unmatched,
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test child exit
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Place barrier and sync with the child. The child only exits()s, which should
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * cause an implicit abortion and wake the parent.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test child exit with sleep
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Same as test_barrier_exit but verifies the test really works due to the
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * child-exit. We add a usleep() which triggers the alarm in the parent and
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * causes the test to time out.
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * Test pending exit against sync
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * The parent places a barrier *and* exits. The 20ms wait in the child
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * guarantees both are pending. However, our logic prefers pending barriers over
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * pending exit-abortions (unlike normal abortions), thus the wait_next() must
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * succeed, same for the sync_next() as our local barrier-count is smaller than
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * the remote. Once we place a barrier our count is equal, so the sync still
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * succeeds. Only if we place one more barrier, we're ahead of the remote, thus
279da1e3f99b9c767a69849b5445e3cfd8d83376David Herrmann * we will fail due to HUP on the pipe.
fd23f9c9a70e1214507641d327da40d1688b74d7David Herrmann * This test uses real-time alarms and sleeps to test for CPU races
fd23f9c9a70e1214507641d327da40d1688b74d7David Herrmann * explicitly. This is highly fragile if your system is under load. We
fd23f9c9a70e1214507641d327da40d1688b74d7David Herrmann * already increased the BASE_TIME value to make the tests more robust,
fd23f9c9a70e1214507641d327da40d1688b74d7David Herrmann * but that just makes the test take significantly longer. Hence,
fd23f9c9a70e1214507641d327da40d1688b74d7David Herrmann * disable the test by default, so it will not break CI.