From a1ebab4192bd54aa0dca1bb0e43d7a4353fe080a Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 19 Feb 2026 20:54:33 +0100 Subject: [PATCH] [utils,signal] split handlers per platform --- libfreerdp/utils/CMakeLists.txt | 7 ++ libfreerdp/utils/signal.c | 204 ++------------------------------ libfreerdp/utils/signal.h | 9 ++ libfreerdp/utils/signal_posix.c | 168 ++++++++++++++++++++++++++ libfreerdp/utils/signal_win32.c | 8 ++ 5 files changed, 204 insertions(+), 192 deletions(-) create mode 100644 libfreerdp/utils/signal.h create mode 100644 libfreerdp/utils/signal_posix.c create mode 100644 libfreerdp/utils/signal_win32.c diff --git a/libfreerdp/utils/CMakeLists.txt b/libfreerdp/utils/CMakeLists.txt index 4c74774a2..b6c2c4ce5 100644 --- a/libfreerdp/utils/CMakeLists.txt +++ b/libfreerdp/utils/CMakeLists.txt @@ -28,6 +28,7 @@ set(${MODULE_PREFIX}_SRCS profiler.c ringbuffer.c signal.c + signal.h string.c gfx.c drdynvc.c @@ -39,6 +40,12 @@ set(${MODULE_PREFIX}_SRCS http.c ) +if(WIN32) + list(APPEND ${MODULE_PREFIX}_SRCS signal_win32.c) +else() + list(APPEND ${MODULE_PREFIX}_SRCS signal_posix.c) +endif() + freerdp_module_add(${${MODULE_PREFIX}_SRCS}) freerdp_library_add(${CMAKE_THREAD_LIBS_INIT}) diff --git a/libfreerdp/utils/signal.c b/libfreerdp/utils/signal.c index cefe975df..90cb34f9a 100644 --- a/libfreerdp/utils/signal.c +++ b/libfreerdp/utils/signal.c @@ -19,46 +19,19 @@ #include -#include -#include #include #include +#include #include #include -#ifndef _WIN32 -#include -#include -#endif +#include "signal.h" #define TAG FREERDP_TAG("utils.signal") -#ifdef _WIN32 - -int freerdp_handle_signals(void) -{ - errno = ENOSYS; - return -1; -} - -BOOL freerdp_add_signal_cleanup_handler(void* context, freerdp_signal_handler_t fkt) -{ - return FALSE; -} - -BOOL freerdp_del_signal_cleanup_handler(void* context, freerdp_signal_handler_t fkt) -{ - return FALSE; -} -#else - -#include -#include - -static BOOL handlers_registered = FALSE; -static pthread_mutex_t signal_handler_lock = PTHREAD_MUTEX_INITIALIZER; +BOOL fsig_handlers_registered = FALSE; typedef struct { @@ -69,29 +42,7 @@ typedef struct static size_t cleanup_handler_count = 0; static cleanup_handler_t cleanup_handlers[20] = { 0 }; -static void lock(void) -{ - const int rc = pthread_mutex_lock(&signal_handler_lock); - if (rc != 0) - { - char ebuffer[256] = { 0 }; - WLog_ERR(TAG, "[pthread_mutex_lock] failed with %s [%d]", - winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc); - } -} - -static void unlock(void) -{ - const int rc = pthread_mutex_unlock(&signal_handler_lock); - if (rc != 0) - { - char ebuffer[256] = { 0 }; - WLog_ERR(TAG, "[pthread_mutex_lock] failed with %s [%d]", - winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc); - } -} - -static void term_handler(int signum) +void fsig_term_handler(int signum) { static BOOL recursive = FALSE; @@ -102,7 +53,7 @@ static void term_handler(int signum) WLog_ERR(TAG, "Caught signal '%s' [%d]", strsignal(signum), signum); } - lock(); + fsig_lock(); for (size_t x = 0; x < cleanup_handler_count; x++) { const cleanup_handler_t empty = { 0 }; @@ -115,143 +66,14 @@ static void term_handler(int signum) *cur = empty; } cleanup_handler_count = 0; - unlock(); -} - -static void fatal_handler(int signum) -{ - struct sigaction default_sigaction; - sigset_t this_mask; - static BOOL recursive = FALSE; - - if (!recursive) - { - recursive = TRUE; - // NOLINTNEXTLINE(concurrency-mt-unsafe) - WLog_ERR(TAG, "Caught signal '%s' [%d]", strsignal(signum), signum); - - winpr_log_backtrace(TAG, WLOG_ERROR, 20); - } - - default_sigaction.sa_handler = SIG_DFL; - sigfillset(&(default_sigaction.sa_mask)); - default_sigaction.sa_flags = 0; - sigaction(signum, &default_sigaction, NULL); - sigemptyset(&this_mask); - sigaddset(&this_mask, signum); - pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL); - (void)raise(signum); -} - -static const int term_signals[] = { SIGINT, SIGKILL, SIGQUIT, SIGSTOP, SIGTERM }; - -static const int fatal_signals[] = { SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, - SIGILL, SIGSEGV, SIGTTIN, SIGTTOU, -#ifdef SIGPOLL - SIGPOLL, -#endif -#ifdef SIGPROF - SIGPROF, -#endif -#ifdef SIGSYS - SIGSYS, -#endif - SIGTRAP, -#ifdef SIGVTALRM - SIGVTALRM, -#endif - SIGXCPU, SIGXFSZ }; - -static BOOL register_handlers(const int* signals, size_t count, void (*handler)(int)) -{ - WINPR_ASSERT(signals || (count == 0)); - WINPR_ASSERT(handler); - - sigset_t orig_set = { 0 }; - struct sigaction saction = { 0 }; - - pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set); - - sigfillset(&(saction.sa_mask)); - sigdelset(&(saction.sa_mask), SIGCONT); - - saction.sa_handler = handler; - saction.sa_flags = 0; - - for (size_t x = 0; x < count; x++) - { - struct sigaction orig_sigaction = { 0 }; - if (sigaction(signals[x], NULL, &orig_sigaction) == 0) - { - if (orig_sigaction.sa_handler != SIG_IGN) - { - sigaction(signals[x], &saction, NULL); - } - } - } - - pthread_sigmask(SIG_SETMASK, &orig_set, NULL); - - return TRUE; -} - -static void unregister_handlers(const int* signals, size_t count) -{ - WINPR_ASSERT(signals || (count == 0)); - - sigset_t orig_set = { 0 }; - struct sigaction saction = { 0 }; - - pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set); - - sigfillset(&(saction.sa_mask)); - sigdelset(&(saction.sa_mask), SIGCONT); - - saction.sa_handler = SIG_IGN; - saction.sa_flags = 0; - - for (size_t x = 0; x < count; x++) - { - sigaction(signals[x], &saction, NULL); - } - - pthread_sigmask(SIG_SETMASK, &orig_set, NULL); -} - -static void unregister_all_handlers(void) -{ - unregister_handlers(fatal_signals, ARRAYSIZE(fatal_signals)); - unregister_handlers(term_signals, ARRAYSIZE(term_signals)); -} - -int freerdp_handle_signals(void) -{ - int rc = -1; - - lock(); - - WLog_DBG(TAG, "Registering signal hook..."); - - (void)atexit(unregister_all_handlers); - if (!register_handlers(fatal_signals, ARRAYSIZE(fatal_signals), fatal_handler)) - goto fail; - if (!register_handlers(term_signals, ARRAYSIZE(term_signals), term_handler)) - goto fail; - - /* Ignore SIGPIPE signal. */ - (void)signal(SIGPIPE, SIG_IGN); - handlers_registered = TRUE; - rc = 0; -fail: - unlock(); - return rc; + fsig_unlock(); } BOOL freerdp_add_signal_cleanup_handler(void* context, freerdp_signal_handler_t handler) { BOOL rc = FALSE; - lock(); - if (handlers_registered) + fsig_lock(); + if (fsig_handlers_registered) { if (cleanup_handler_count < ARRAYSIZE(cleanup_handlers)) { @@ -264,15 +86,15 @@ BOOL freerdp_add_signal_cleanup_handler(void* context, freerdp_signal_handler_t ARRAYSIZE(cleanup_handlers)); } rc = TRUE; - unlock(); + fsig_unlock(); return rc; } BOOL freerdp_del_signal_cleanup_handler(void* context, freerdp_signal_handler_t handler) { BOOL rc = FALSE; - lock(); - if (handlers_registered) + fsig_lock(); + if (fsig_handlers_registered) { for (size_t x = 0; x < cleanup_handler_count; x++) { @@ -292,8 +114,6 @@ BOOL freerdp_del_signal_cleanup_handler(void* context, freerdp_signal_handler_t } } rc = TRUE; - unlock(); + fsig_unlock(); return rc; } - -#endif diff --git a/libfreerdp/utils/signal.h b/libfreerdp/utils/signal.h new file mode 100644 index 000000000..b6f9ca8da --- /dev/null +++ b/libfreerdp/utils/signal.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +extern BOOL fsig_handlers_registered; + +void fsig_lock(void); +void fsig_unlock(void); +void fsig_term_handler(int signum); diff --git a/libfreerdp/utils/signal_posix.c b/libfreerdp/utils/signal_posix.c new file mode 100644 index 000000000..1ce761aa6 --- /dev/null +++ b/libfreerdp/utils/signal_posix.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "signal.h" + +#define TAG FREERDP_TAG("utils.signal.posix") + +static pthread_mutex_t signal_handler_lock = PTHREAD_MUTEX_INITIALIZER; + +void fsig_lock(void) +{ + const int rc = pthread_mutex_lock(&signal_handler_lock); + if (rc != 0) + { + char ebuffer[256] = { 0 }; + WLog_ERR(TAG, "[pthread_mutex_lock] failed with %s [%d]", + winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc); + } +} + +void fsig_unlock(void) +{ + const int rc = pthread_mutex_unlock(&signal_handler_lock); + if (rc != 0) + { + char ebuffer[256] = { 0 }; + WLog_ERR(TAG, "[pthread_mutex_lock] failed with %s [%d]", + winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc); + } +} + +static void fatal_handler(int signum) +{ + struct sigaction default_sigaction; + sigset_t this_mask; + static BOOL recursive = FALSE; + + if (!recursive) + { + recursive = TRUE; + // NOLINTNEXTLINE(concurrency-mt-unsafe) + WLog_ERR(TAG, "Caught signal '%s' [%d]", strsignal(signum), signum); + + winpr_log_backtrace(TAG, WLOG_ERROR, 20); + } + + default_sigaction.sa_handler = SIG_DFL; + sigfillset(&(default_sigaction.sa_mask)); + default_sigaction.sa_flags = 0; + sigaction(signum, &default_sigaction, NULL); + sigemptyset(&this_mask); + sigaddset(&this_mask, signum); + pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL); + (void)raise(signum); +} + +static const int term_signals[] = { SIGINT, SIGKILL, SIGQUIT, SIGSTOP, SIGTERM }; + +static const int fatal_signals[] = { SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, + SIGILL, SIGSEGV, SIGTTIN, SIGTTOU, +#ifdef SIGPOLL + SIGPOLL, +#endif +#ifdef SIGPROF + SIGPROF, +#endif +#ifdef SIGSYS + SIGSYS, +#endif + SIGTRAP, +#ifdef SIGVTALRM + SIGVTALRM, +#endif + SIGXCPU, SIGXFSZ }; + +static BOOL register_handlers(const int* signals, size_t count, void (*handler)(int)) +{ + WINPR_ASSERT(signals || (count == 0)); + WINPR_ASSERT(handler); + + sigset_t orig_set = { 0 }; + struct sigaction saction = { 0 }; + + pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set); + + sigfillset(&(saction.sa_mask)); + sigdelset(&(saction.sa_mask), SIGCONT); + + saction.sa_handler = handler; + saction.sa_flags = 0; + + for (size_t x = 0; x < count; x++) + { + struct sigaction orig_sigaction = { 0 }; + if (sigaction(signals[x], NULL, &orig_sigaction) == 0) + { + if (orig_sigaction.sa_handler != SIG_IGN) + { + sigaction(signals[x], &saction, NULL); + } + } + } + + pthread_sigmask(SIG_SETMASK, &orig_set, NULL); + + return TRUE; +} + +static void unregister_handlers(const int* signals, size_t count) +{ + WINPR_ASSERT(signals || (count == 0)); + + sigset_t orig_set = { 0 }; + struct sigaction saction = { 0 }; + + pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set); + + sigfillset(&(saction.sa_mask)); + sigdelset(&(saction.sa_mask), SIGCONT); + + saction.sa_handler = SIG_IGN; + saction.sa_flags = 0; + + for (size_t x = 0; x < count; x++) + { + sigaction(signals[x], &saction, NULL); + } + + pthread_sigmask(SIG_SETMASK, &orig_set, NULL); +} + +static void unregister_all_handlers(void) +{ + unregister_handlers(fatal_signals, ARRAYSIZE(fatal_signals)); + unregister_handlers(term_signals, ARRAYSIZE(term_signals)); +} + +int freerdp_handle_signals(void) +{ + int rc = -1; + + fsig_lock(); + + WLog_DBG(TAG, "Registering signal hook..."); + + (void)atexit(unregister_all_handlers); + if (!register_handlers(fatal_signals, ARRAYSIZE(fatal_signals), fatal_handler)) + goto fail; + if (!register_handlers(term_signals, ARRAYSIZE(term_signals), fsig_term_handler)) + goto fail; + + /* Ignore SIGPIPE signal. */ + (void)signal(SIGPIPE, SIG_IGN); + fsig_handlers_registered = TRUE; + rc = 0; +fail: + fsig_unlock(); + return rc; +} diff --git a/libfreerdp/utils/signal_win32.c b/libfreerdp/utils/signal_win32.c new file mode 100644 index 000000000..c6e2e075a --- /dev/null +++ b/libfreerdp/utils/signal_win32.c @@ -0,0 +1,8 @@ +#include +#include + +int freerdp_handle_signals(void) +{ + errno = ENOSYS; + return -1; +}