diff options
Diffstat (limited to 'src/lib/test-lib-signals.c')
-rw-r--r-- | src/lib/test-lib-signals.c | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/src/lib/test-lib-signals.c b/src/lib/test-lib-signals.c new file mode 100644 index 0000000..75d324a --- /dev/null +++ b/src/lib/test-lib-signals.c @@ -0,0 +1,245 @@ +/* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "time-util.h" +#include "ioloop.h" +#include "lib-signals.h" + +#include <unistd.h> +#include <sys/types.h> + +struct test_context_delayed { + bool timed_out:1; + bool signal_handled:1; +}; + +static void +kill_timeout(struct test_context_delayed *tctx ATTR_UNUSED) +{ + if (kill(getpid(), SIGALRM) < 0) + i_fatal("Failed to send signal: %m"); +} + +static void +test_timeout(struct test_context_delayed *tctx) +{ + tctx->timed_out = TRUE; + io_loop_stop(current_ioloop); +} + +static void +signal_handler_delayed(const siginfo_t *si ATTR_UNUSED, + void *context ATTR_UNUSED) +{ + struct test_context_delayed *tctx = + (struct test_context_delayed *)context; + tctx->signal_handled = TRUE; + io_loop_stop(current_ioloop); +} + +static void +test_lib_signals_delayed(void) +{ + struct test_context_delayed tctx; + struct timeout *to_kill, *to_test; + struct ioloop *ioloop; + + test_begin("lib-signals delayed - init lib-signals first"); + + i_zero(&tctx); + + lib_signals_init(); + lib_signals_set_handler(SIGALRM, + LIBSIG_FLAGS_SAFE | LIBSIG_FLAG_IOLOOP_AUTOMOVE, + signal_handler_delayed, &tctx); + + ioloop = io_loop_create(); + to_kill = timeout_add_short(200, kill_timeout, &tctx); + to_test = timeout_add_short(400, test_timeout, &tctx); + io_loop_run(ioloop); + + timeout_remove(&to_kill); + timeout_remove(&to_test); + io_loop_destroy(&ioloop); + + lib_signals_deinit(); + + test_assert(!tctx.timed_out); + test_assert(tctx.signal_handled); + + test_end(); + + test_begin("lib-signals delayed - init ioloop first"); + + i_zero(&tctx); + + ioloop = io_loop_create(); + + lib_signals_init(); + lib_signals_set_handler(SIGALRM, + LIBSIG_FLAGS_SAFE | LIBSIG_FLAG_IOLOOP_AUTOMOVE, + signal_handler_delayed, &tctx); + + to_kill = timeout_add_short(200, kill_timeout, &tctx); + to_test = timeout_add_short(400, test_timeout, &tctx); + io_loop_run(ioloop); + + timeout_remove(&to_kill); + timeout_remove(&to_test); + + lib_signals_deinit(); + + io_loop_destroy(&ioloop); + + test_assert(!tctx.timed_out); + test_assert(tctx.signal_handled); + + test_end(); + +} + +static void +test_lib_signals_delayed_nested_ioloop(void) +{ + struct test_context_delayed tctx; + struct timeout *to_kill, *to_test; + struct ioloop *ioloop1, *ioloop2; + + test_begin("lib-signals delayed in nested ioloop"); + + i_zero(&tctx); + + lib_signals_init(); + lib_signals_set_handler(SIGALRM, + LIBSIG_FLAGS_SAFE | LIBSIG_FLAG_IOLOOP_AUTOMOVE, + signal_handler_delayed, &tctx); + + /* briefly run outer ioloop */ + ioloop1 = io_loop_create(); + to_test = timeout_add_short(100, test_timeout, &tctx); + io_loop_run(ioloop1); + timeout_remove(&to_test); + test_assert(tctx.timed_out); + test_assert(!tctx.signal_handled); + tctx.timed_out = FALSE; + + /* run inner ioloop, which triggers the signal */ + ioloop2 = io_loop_create(); + to_kill = timeout_add_short(200, kill_timeout, &tctx); + to_test = timeout_add_short(400, test_timeout, &tctx); + io_loop_run(ioloop2); + + timeout_remove(&to_kill); + timeout_remove(&to_test); + io_loop_destroy(&ioloop2); + + io_loop_destroy(&ioloop1); + + lib_signals_deinit(); + + test_assert(!tctx.timed_out); + test_assert(tctx.signal_handled); + + test_end(); +} + +static void +test_lib_signals_delayed_no_ioloop_automove(void) +{ + struct test_context_delayed tctx; + struct timeout *to_kill, *to_test; + struct ioloop *ioloop1, *ioloop2; + + test_begin("lib-signals delayed with NO_IOLOOP_AUTOMOVE - unmoved"); + + i_zero(&tctx); + + ioloop1 = io_loop_create(); + + lib_signals_init(); + lib_signals_set_handler(SIGALRM, LIBSIG_FLAGS_SAFE, + signal_handler_delayed, &tctx); + + /* briefly run outer ioloop */ + to_test = timeout_add_short(100, test_timeout, &tctx); + io_loop_run(ioloop1); + timeout_remove(&to_test); + test_assert(tctx.timed_out); + test_assert(!tctx.signal_handled); + tctx.timed_out = FALSE; + + /* run inner ioloop, which triggers the signal but musn't handle it */ + ioloop2 = io_loop_create(); + to_kill = timeout_add_short(200, kill_timeout, &tctx); + to_test = timeout_add_short(400, test_timeout, &tctx); + io_loop_run(ioloop2); + + test_assert(tctx.timed_out); + test_assert(!tctx.signal_handled); + tctx.timed_out = FALSE; + + timeout_remove(&to_kill); + timeout_remove(&to_test); + io_loop_destroy(&ioloop2); + + /* run outer ioloop once more */ + to_test = timeout_add_short(100, test_timeout, &tctx); + io_loop_run(ioloop1); + timeout_remove(&to_test); + + lib_signals_deinit(); + + io_loop_destroy(&ioloop1); + + test_assert(!tctx.timed_out); + test_assert(tctx.signal_handled); + + test_end(); + + test_begin("lib-signals delayed with NO_IOLOOP_AUTOMOVE - moved"); + + i_zero(&tctx); + + ioloop1 = io_loop_create(); + + lib_signals_init(); + lib_signals_set_handler(SIGALRM, LIBSIG_FLAGS_SAFE, + signal_handler_delayed, &tctx); + + /* briefly run outer ioloop */ + to_test = timeout_add_short(100, test_timeout, &tctx); + io_loop_run(ioloop1); + timeout_remove(&to_test); + test_assert(tctx.timed_out); + test_assert(!tctx.signal_handled); + tctx.timed_out = FALSE; + + /* run inner ioloop, which triggers the signal */ + ioloop2 = io_loop_create(); + lib_signals_switch_ioloop(SIGALRM, + signal_handler_delayed, &tctx); + + to_kill = timeout_add_short(200, kill_timeout, &tctx); + to_test = timeout_add_short(400, test_timeout, &tctx); + io_loop_run(ioloop2); + + test_assert(!tctx.timed_out); + test_assert(tctx.signal_handled); + + timeout_remove(&to_kill); + timeout_remove(&to_test); + io_loop_destroy(&ioloop2); + + lib_signals_deinit(); + io_loop_destroy(&ioloop1); + + test_end(); +} + + +void test_lib_signals(void) +{ + test_lib_signals_delayed(); + test_lib_signals_delayed_nested_ioloop(); + test_lib_signals_delayed_no_ioloop_automove(); +} |