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 <lkn@darkstar.example.net>
This commit is contained in:
Levi Neely 2026-03-08 14:27:21 +01:00 committed by GitHub
parent 9d4143f1f0
commit 89ef8663b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 105 additions and 23 deletions

View File

@ -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();
}

71
pclsync/psignal.c Normal file
View File

@ -0,0 +1,71 @@
#include "psignal.h"
#include <signal.h>
#include <stddef.h>
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;
}

18
pclsync/psignal.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef PSIGNAL_H
#define PSIGNAL_H
#include <signal.h>
#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

View File

@ -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);

View File

@ -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());
}