From 89ef8663b0d79b0efea82d689e95eeef3469e679 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sun, 8 Mar 2026 14:27:21 +0100 Subject: [PATCH] Add psignal module for centralized signal handling (#368) * Add psignal module for centralized signal handling - Added pclsync/psignal.h with psignal_register() and psignal_check_pending() API - Added pclsync/psignal.c with async-signal-safe handlers for SIGINT, SIGTERM, SIGHUP - Implements flag-based deferred signal handling pattern * Integrate psignal into main loop and remove conflicting handlers - Added extern "C" linkage to psignal.h for C++ compatibility - Integrated psignal_check_pending() into pclsync_lib.cpp main loop - Integrated psignal_check_pending() into ptimer.c timer loop - Removed conflicting signal handlers from pfs.c * Migrate psync_set_signal to psignal module - Added psignal_set_custom_handler() to psignal.h and psignal.c - Replaced psync_set_signal() calls in pfs.c with psignal_set_custom_handler() - Centralizes all signal handling in psignal module --------- Co-authored-by: Levi Neely --- pclsync/pfs.c | 26 ++--------------- pclsync/psignal.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ pclsync/psignal.h | 18 ++++++++++++ pclsync/ptimer.c | 8 ++++++ pclsync_lib.cpp | 5 ++++ 5 files changed, 105 insertions(+), 23 deletions(-) create mode 100644 pclsync/psignal.c create mode 100644 pclsync/psignal.h diff --git a/pclsync/pfs.c b/pclsync/pfs.c index 5a9987c..6d22621 100644 --- a/pclsync/pfs.c +++ b/pclsync/pfs.c @@ -3601,28 +3601,7 @@ static void psync_usr2_handler(int sig) { pdbg_reopen_log(); } -static void psync_set_signal(int sig, void (*handler)(int)) { - struct sigaction sa; - - if (pdbg_unlikely(sigaction(sig, NULL, &sa))) - return; - - if (sa.sa_handler == SIG_DFL) { - memset(&sa, 0, sizeof(struct sigaction)); - sigemptyset(&(sa.sa_mask)); - sa.sa_handler = handler; - sa.sa_flags = 0; - sigaction(sig, &sa, NULL); - } -} - -static void psync_setup_signals() { - psync_set_signal(SIGTERM, psync_signal_handler); - psync_set_signal(SIGINT, psync_signal_handler); - psync_set_signal(SIGHUP, psync_signal_handler); - pfs_debug_register_signal_handlers(); - psync_set_signal(SIGUSR2, psync_usr2_handler); -} +#include "psignal.h" static void pfs_init_once() { #if pfs_need_per_folder_refresh_const() @@ -3637,7 +3616,8 @@ static void pfs_init_once() { pfs_task_init(); ppagecache_init(); atexit(pfs_do_stop); - psync_setup_signals(); + pfs_debug_register_signal_handlers(); + psignal_set_custom_handler(SIGUSR2, psync_usr2_handler); pfs_stat_add_files(); pfs_task_add_banned_folders(); } diff --git a/pclsync/psignal.c b/pclsync/psignal.c new file mode 100644 index 0000000..d7a0788 --- /dev/null +++ b/pclsync/psignal.c @@ -0,0 +1,71 @@ +#include "psignal.h" +#include +#include + +static volatile sig_atomic_t sigint_flag = 0; +static volatile sig_atomic_t sigterm_flag = 0; +static volatile sig_atomic_t sighup_flag = 0; + +static void sigint_handler(int sig) { + sigint_flag = 1; +} + +static void sigterm_handler(int sig) { + sigterm_flag = 1; +} + +static void sighup_handler(int sig) { + sighup_flag = 1; +} + +void psignal_set_custom_handler(int sig, void (*handler)(int)) { + struct sigaction sa; + + if (sigaction(sig, NULL, &sa) != 0) + return; + + if (sa.sa_handler == SIG_DFL) { + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(sig, &sa, NULL) != 0) { + return; + } + } +} + +void psignal_register(int signum) { + void (*handler)(int) = NULL; + + if (signum == SIGINT) { + handler = sigint_handler; + } else if (signum == SIGTERM) { + handler = sigterm_handler; + } else if (signum == SIGHUP) { + handler = sighup_handler; + } else { + return; + } + + psignal_set_custom_handler(signum, handler); +} + +int psignal_check_pending(void) { + sig_atomic_t int_flag = sigint_flag; + sig_atomic_t term_flag = sigterm_flag; + sig_atomic_t hup_flag = sighup_flag; + + if (int_flag) { + sigint_flag = 0; + return SIGINT; + } + if (term_flag) { + sigterm_flag = 0; + return SIGTERM; + } + if (hup_flag) { + sighup_flag = 0; + return SIGHUP; + } + return 0; +} diff --git a/pclsync/psignal.h b/pclsync/psignal.h new file mode 100644 index 0000000..c6a792b --- /dev/null +++ b/pclsync/psignal.h @@ -0,0 +1,18 @@ +#ifndef PSIGNAL_H +#define PSIGNAL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void psignal_register(int signum); +int psignal_check_pending(void); +void psignal_set_custom_handler(int sig, void (*handler)(int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pclsync/ptimer.c b/pclsync/ptimer.c index e94290a..161910d 100644 --- a/pclsync/ptimer.c +++ b/pclsync/ptimer.c @@ -35,6 +35,7 @@ #include "prun.h" #include "psys.h" #include "ptimer.h" +#include "psignal.h" /* Maximum timeout possible is TIMER_ARRAY_SIZE^TIMER_LEVELS seconds, in the * worst case TIMER_LEVELS operations will be preformed for each timer to @@ -145,8 +146,15 @@ PSYNC_NOINLINE static void timer_process_timers(psync_list *timers) { static void timer_thread() { psync_list timers; time_t lt; + int sig; lt = __atomic_load_n(&psync_current_time, __ATOMIC_RELAXED); while (psync_do_run) { + sig = psignal_check_pending(); + if (sig) { + pdbg_logf(D_NOTICE, "received signal %d, shutting down", sig); + psync_do_run = 0; + break; + } psync_list_init(&timers); psys_sleep_milliseconds(1000); __atomic_store_n(&psync_current_time, psys_time_seconds(), __ATOMIC_RELAXED); diff --git a/pclsync_lib.cpp b/pclsync_lib.cpp index 878bce9..fbe819d 100644 --- a/pclsync_lib.cpp +++ b/pclsync_lib.cpp @@ -50,6 +50,7 @@ #include "pclsync/pdbg.h" #include "pclsync/psock.h" #include "pclsync/plibs.h" +#include "pclsync/psignal.h" #include "pclsync_lib.h" @@ -668,6 +669,10 @@ int clib::pclsync_lib::init() { was_init_ = true; + psignal_register(SIGINT); + psignal_register(SIGTERM); + psignal_register(SIGHUP); + if (!get_mount().empty()) { psync_set_string_setting("fsroot", get_mount().c_str()); }