From d11617adbef0d7a31874366e7fad790b7c12e571 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:29:06 +0100 Subject: [PATCH] Remove dependency on signal() function Replaces uses of signal() with sigaction() which should be far more portable. --- common/os_calls.c | 135 +++++++++++++++++++++++++++++--- common/os_calls.h | 51 ++++++++++++ tests/common/Makefile.am | 1 + tests/common/test_common.h | 5 ++ tests/common/test_common_main.c | 5 +- tests/common/test_os_calls.c | 4 + 6 files changed, 191 insertions(+), 10 deletions(-) diff --git a/common/os_calls.c b/common/os_calls.c index 1afeb570..6739a647 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -2987,10 +2987,28 @@ g_set_alarm(void (*func)(int), unsigned int secs) #if defined(_WIN32) return 0; #else + struct sigaction action; + /* Cancel any previous alarm to prevent a race */ unsigned int rv = alarm(0); - signal(SIGALRM, func); - (void)alarm(secs); + + if (func == NULL) + { + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + } + else + { + action.sa_handler = func; + action.sa_flags = SA_RESTART; + } + sigemptyset (&action.sa_mask); + + sigaction(SIGALRM, &action, NULL); + if (func != NULL && secs > 0) + { + (void)alarm(secs); + } return rv; #endif } @@ -3002,7 +3020,22 @@ g_signal_child_stop(void (*func)(int)) { #if defined(_WIN32) #else - signal(SIGCHLD, func); + struct sigaction action; + + if (func == NULL) + { + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + } + else + { + action.sa_handler = func; + // Don't need to know when children are stopped or started + action.sa_flags = (SA_RESTART | SA_NOCLDSTOP); + } + sigemptyset (&action.sa_mask); + + sigaction(SIGCHLD, &action, NULL); #endif } @@ -3013,7 +3046,21 @@ g_signal_segfault(void (*func)(int)) { #if defined(_WIN32) #else - signal(SIGSEGV, func); + struct sigaction action; + + if (func == NULL) + { + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + } + else + { + action.sa_handler = func; + action.sa_flags = SA_RESETHAND; // This is a one-shot + } + sigemptyset (&action.sa_mask); + + sigaction(SIGSEGV, &action, NULL); #endif } @@ -3024,7 +3071,21 @@ g_signal_hang_up(void (*func)(int)) { #if defined(_WIN32) #else - signal(SIGHUP, func); + struct sigaction action; + + if (func == NULL) + { + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + } + else + { + action.sa_handler = func; + action.sa_flags = SA_RESTART; + } + sigemptyset (&action.sa_mask); + + sigaction(SIGHUP, &action, NULL); #endif } @@ -3035,7 +3096,21 @@ g_signal_user_interrupt(void (*func)(int)) { #if defined(_WIN32) #else - signal(SIGINT, func); + struct sigaction action; + + if (func == NULL) + { + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + } + else + { + action.sa_handler = func; + action.sa_flags = SA_RESTART; + } + sigemptyset (&action.sa_mask); + + sigaction(SIGINT, &action, NULL); #endif } @@ -3046,7 +3121,21 @@ g_signal_terminate(void (*func)(int)) { #if defined(_WIN32) #else - signal(SIGTERM, func); + struct sigaction action; + + if (func == NULL) + { + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + } + else + { + action.sa_handler = func; + action.sa_flags = SA_RESTART; + } + sigemptyset (&action.sa_mask); + + sigaction(SIGTERM, &action, NULL); #endif } @@ -3057,7 +3146,21 @@ g_signal_pipe(void (*func)(int)) { #if defined(_WIN32) #else - signal(SIGPIPE, func); + struct sigaction action; + + if (func == NULL) + { + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + } + else + { + action.sa_handler = func; + action.sa_flags = SA_RESTART; + } + sigemptyset (&action.sa_mask); + + sigaction(SIGPIPE, &action, NULL); #endif } @@ -3068,7 +3171,21 @@ g_signal_usr1(void (*func)(int)) { #if defined(_WIN32) #else - signal(SIGUSR1, func); + struct sigaction action; + + if (func == NULL) + { + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + } + else + { + action.sa_handler = func; + action.sa_flags = SA_RESTART; + } + sigemptyset (&action.sa_mask); + + sigaction(SIGUSR1, &action, NULL); #endif } diff --git a/common/os_calls.h b/common/os_calls.h index 2d5c18e6..6579d116 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -176,6 +176,14 @@ g_sck_get_peer_ip_address(int sck, const char * g_sck_get_peer_description(int sck, char *desc, unsigned int bytes); +/** + * Sleep for the specified number of milli-seconds + * @param msecs Milli-seconds + * + * If a signal is processed, it is possible that this call will + * sleep for less than the specified number of milli-seconds. This + * is platform-specific + */ void g_sleep(int msecs); int g_pipe(int fd[2]); @@ -275,13 +283,56 @@ int g_execvp(const char *p1, char *args[]); */ int g_execvp_list(const char *file, struct list *argv); int g_execlp3(const char *a1, const char *a2, const char *a3); +/** + * Set an alarm using SIGALRM + * @param func Signal handler, or NULL to cancel an alarm + * @param secs Number of seconds until an alarm is raised + * @return Number of seconds remaining before a previously requested + * alarm is raised + */ unsigned int g_set_alarm(void (*func)(int), unsigned int secs); +/** + * Set a handler up for SIGCHLD + * @param func signal handler, or NULL to restore the default handler + * The handler remains in place until explicitly replaced. + */ void g_signal_child_stop(void (*func)(int)); +/** + * Set a handler up for SIGSEGV + * @param func signal handler, or NULL to restore the default handler + * The handler can only be called once, at which point the + * default handler is restored. This is to avoid infinite loops + */ void g_signal_segfault(void (*func)(int)); +/** + * Set a handler up for SIGHUP + * @param func signal handler, or NULL to restore the default handler + * The handler remains in place until explicitly replaced. + */ void g_signal_hang_up(void (*func)(int)); +/** + * Set a handler up for SIGINT + * @param func signal handler, or NULL to restore the default handler + * The handler remains in place until explicitly replaced. + */ void g_signal_user_interrupt(void (*func)(int)); +/** + * Set a handler up for SIGTERM + * @param func signal handler, or NULL to restore the default handler + * The handler remains in place until explicitly replaced. + */ void g_signal_terminate(void (*func)(int)); +/** + * Set a handler up for SIGPIPE + * @param func signal handler, or NULL to restore the default handler + * The handler remains in place until explicitly replaced. + */ void g_signal_pipe(void (*func)(int)); +/** + * Set a handler up for SIGUSR1 + * @param func signal handler, or NULL to restore the default handler + * The handler remains in place until explicitly replaced. + */ void g_signal_usr1(void (*func)(int)); int g_fork(void); int g_setgid(int pid); diff --git a/tests/common/Makefile.am b/tests/common/Makefile.am index de4b0a3c..8294afcb 100644 --- a/tests/common/Makefile.am +++ b/tests/common/Makefile.am @@ -18,6 +18,7 @@ test_common_SOURCES = \ test_list_calls.c \ test_string_calls.c \ test_os_calls.c \ + test_os_calls_signals.c \ test_ssl_calls.c \ test_base64.c \ test_guid.c diff --git a/tests/common/test_common.h b/tests/common/test_common.h index 09f3acf1..ea700c30 100644 --- a/tests/common/test_common.h +++ b/tests/common/test_common.h @@ -15,4 +15,9 @@ Suite *make_suite_test_ssl_calls(void); Suite *make_suite_test_base64(void); Suite *make_suite_test_guid(void); +TCase *make_tcase_test_os_calls_signals(void); + +void os_calls_signals_init(void); +void os_calls_signals_deinit(void); + #endif /* TEST_COMMON_H */ diff --git a/tests/common/test_common_main.c b/tests/common/test_common_main.c index ec3f579d..05eacd27 100644 --- a/tests/common/test_common_main.c +++ b/tests/common/test_common_main.c @@ -64,14 +64,17 @@ int main (void) * reporting when running in libcheck fork mode */ setvbuf(stdout, NULL, _IONBF, 0); - /* Initialise the ssl module */ + /* Initialise modules */ ssl_init(); + os_calls_signals_init(); srunner_run_all (sr, CK_ENV); number_failed = srunner_ntests_failed(sr); srunner_free(sr); ssl_finish(); + os_calls_signals_deinit(); + log_end(); return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/common/test_os_calls.c b/tests/common/test_os_calls.c index e0f44bbc..c2a3e09e 100644 --- a/tests/common/test_os_calls.c +++ b/tests/common/test_os_calls.c @@ -512,5 +512,9 @@ make_suite_test_os_calls(void) tcase_add_test(tc_os_calls, test_g_file_is_open); tcase_add_test(tc_os_calls, test_g_sck_fd_passing); tcase_add_test(tc_os_calls, test_g_sck_fd_overflow); + + // Add other test cases in other files + suite_add_tcase(s, make_tcase_test_os_calls_signals()); + return s; }