From d6807dc8d47b694ecb4ca6282c05cfa955d4d3a6 Mon Sep 17 00:00:00 2001 From: PobreGato <315121269+pobregat0@users.noreply.github.com> Date: Tue, 11 Aug 2026 04:53:32 +0300 Subject: [PATCH] don't call unsafe functions from signal handler --- daemon/UnixDaemon.cpp | 88 ++++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index 88b5d74d..47ad2041 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -10,6 +10,7 @@ #ifndef _WIN32 +#include #include #include #include @@ -27,43 +28,61 @@ #include "Transports.h" #include "util.h" +const int GRACEFUL_SHUTDOWN_INTERVAL = 10*60; // in seconds + +// a handler may only touch volatile sig_atomic_t, everything else is done by the daemon loop +static volatile sig_atomic_t g_PendingSignals[NSIG] = {}; + void handle_signal(int sig) { - switch (sig) + int savedErrno = errno; + if (sig > 0 && sig < NSIG) + g_PendingSignals[sig] = 1; + errno = savedErrno; +} + +static void HandlePendingSignals() +{ + for (int sig = 1; sig < NSIG; sig++) { - case SIGHUP: - LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening tunnel configuration..."); - i2p::client::context.ReloadConfig(); - break; - case SIGUSR1: - LogPrint(eLogInfo, "Daemon: Got SIGUSR1, reopening logs..."); - i2p::log::Logger().Reopen (); - break; - case SIGINT: - if (i2p::context.AcceptsTunnels () && !Daemon.gracefulShutdownInterval) - { - i2p::context.SetAcceptsTunnels (false); - Daemon.gracefulShutdownInterval = 10*60; // 10 minutes - LogPrint(eLogInfo, "Graceful shutdown after ", Daemon.gracefulShutdownInterval, " seconds"); - } - else - Daemon.running = 0; - break; - case SIGABRT: - case SIGTERM: - Daemon.running = 0; // Exit loop - break; - case SIGPIPE: - LogPrint(eLogInfo, "SIGPIPE received"); - break; - case SIGTSTP: - LogPrint(eLogInfo, "Daemon: Got SIGTSTP, disconnecting from network..."); - i2p::transport::transports.SetOnline(false); - break; - case SIGCONT: - LogPrint(eLogInfo, "Daemon: Got SIGCONT, restoring connection to network..."); - i2p::transport::transports.SetOnline(true); - break; + if (!g_PendingSignals[sig]) continue; + g_PendingSignals[sig] = 0; + switch (sig) + { + case SIGHUP: + LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening tunnel configuration..."); + i2p::client::context.ReloadConfig(); + break; + case SIGUSR1: + LogPrint(eLogInfo, "Daemon: Got SIGUSR1, reopening logs..."); + i2p::log::Logger().Reopen (); + break; + case SIGINT: + if (i2p::context.AcceptsTunnels () && !Daemon.gracefulShutdownInterval) + { + i2p::context.SetAcceptsTunnels (false); + Daemon.gracefulShutdownInterval = GRACEFUL_SHUTDOWN_INTERVAL; + LogPrint(eLogInfo, "Graceful shutdown after ", Daemon.gracefulShutdownInterval, " seconds"); + } + else + Daemon.running = 0; + break; + case SIGABRT: + case SIGTERM: + Daemon.running = 0; // Exit loop + break; + case SIGPIPE: + LogPrint(eLogInfo, "SIGPIPE received"); + break; + case SIGTSTP: + LogPrint(eLogInfo, "Daemon: Got SIGTSTP, disconnecting from network..."); + i2p::transport::transports.SetOnline(false); + break; + case SIGCONT: + LogPrint(eLogInfo, "Daemon: Got SIGCONT, restoring connection to network..."); + i2p::transport::transports.SetOnline(true); + break; + } } } @@ -225,6 +244,7 @@ namespace i2p while (running) { std::this_thread::sleep_for (std::chrono::seconds(1)); + HandlePendingSignals(); if (gracefulShutdownInterval) { gracefulShutdownInterval--; // - 1 second