From 9a37bb659b8ec1586d6485108fe8c797cae66f9d Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Tue, 13 Oct 2026 00:24:43 -0600 Subject: [PATCH] windows: reopen log files with service control code Windows has no SIGHUP and no unix socket, so Suricata could not be told to reopen its log files after external log rotation. When running as a service, this can now be requested with the user-defined control code 129, for example: sc.exe control Suricata 129 The service control handler only records the request; the main loop then handles it the same as SIGHUP. Ticket: 7757 --- doc/userguide/manpages/suricata.rst | 4 ++-- doc/userguide/output/log-rotation.rst | 17 +++++++++++++++++ src/suricata.c | 7 ++++++- src/win32-service.c | 6 ++++++ src/win32-service.h | 6 ++++-- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/doc/userguide/manpages/suricata.rst b/doc/userguide/manpages/suricata.rst index a85795c01a..17de1f9f6a 100644 --- a/doc/userguide/manpages/suricata.rst +++ b/doc/userguide/manpages/suricata.rst @@ -45,8 +45,8 @@ SIGHUP used to re-open log files after they may have been moved away by log rotation utilities. -On Windows, when running as a service, the service control code 128 is the -equivalent of SIGUSR2. +On Windows, when running as a service, the service control codes 128 and +129 are the equivalent of SIGUSR2 and SIGHUP respectively. FILES AND DIRECTORIES --------------------- diff --git a/doc/userguide/output/log-rotation.rst b/doc/userguide/output/log-rotation.rst index d6f00932fc..250f743a28 100644 --- a/doc/userguide/output/log-rotation.rst +++ b/doc/userguide/output/log-rotation.rst @@ -44,3 +44,20 @@ include: - :ref:`Eve ` - :ref:`PCAP log ` + +Windows +------- + +Windows does not support SIGHUP. Instead, when Suricata is running as a +Windows service, it can be told to re-open its log files by sending the +service the user-defined control code ``129``:: + + sc.exe control Suricata 129 + +As with SIGHUP, an external tool is responsible for renaming the log files +before sending the control code. Suricata opens log files on Windows with +shared delete access so they can be renamed while open. See +:ref:`rule-reload-windows-service` for who may send control codes. + +.. note:: In PowerShell, ``sc`` is an alias for ``Set-Content``, so + ``sc.exe`` must be used. diff --git a/src/suricata.c b/src/suricata.c index 0da0dac37e..e9a377421d 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -3042,8 +3042,13 @@ void SuricataMainLoop(void) #ifdef OS_WIN32 /* Service control requests are handled like their signal equivalents, - * SC_SERVICE_REQUEST_RELOAD_RULES like SIGUSR2. */ + * SC_SERVICE_REQUEST_RELOAD_RULES like SIGUSR2 and + * SC_SERVICE_REQUEST_REOPEN_LOG_FILES like SIGHUP. */ uint32_t requests = SCServiceTakeRequests(); + if (requests & SC_SERVICE_REQUEST_REOPEN_LOG_FILES) { + SCLogNotice("Reopen of log files requested by service control"); + sighup_count = 1; + } if (requests & SC_SERVICE_REQUEST_RELOAD_RULES) { SCLogNotice("Rule reload requested by service control"); if (DetectEngineEnabled() && sigusr2_count < 2) { diff --git a/src/win32-service.c b/src/win32-service.c index c3b3d64930..25caa36f7a 100644 --- a/src/win32-service.c +++ b/src/win32-service.c @@ -209,6 +209,12 @@ static DWORD WINAPI SCServiceCtrlHandlerEx(DWORD code, DWORD etype, LPVOID edata return NO_ERROR; } + if (code == SC_SERVICE_CONTROL_REOPEN_LOG_FILES) { + /* Defer logging to the main loop, after logging initialization. */ + SC_ATOMIC_OR(service_requests, SC_SERVICE_REQUEST_REOPEN_LOG_FILES); + return NO_ERROR; + } + if (code == SERVICE_CONTROL_SHUTDOWN || code == SERVICE_CONTROL_STOP) { SERVICE_STATUS status = { SERVICE_WIN32, diff --git a/src/win32-service.h b/src/win32-service.h index bb808fe85a..afcc5ce754 100644 --- a/src/win32-service.h +++ b/src/win32-service.h @@ -26,10 +26,12 @@ #ifdef OS_WIN32 /* User-defined service control codes, must be in the range 128-255. */ -#define SC_SERVICE_CONTROL_RELOAD_RULES 128 +#define SC_SERVICE_CONTROL_RELOAD_RULES 128 +#define SC_SERVICE_CONTROL_REOPEN_LOG_FILES 129 /* Requests returned by SCServiceTakeRequests(). */ -#define SC_SERVICE_REQUEST_RELOAD_RULES BIT_U32(0) +#define SC_SERVICE_REQUEST_RELOAD_RULES BIT_U32(0) +#define SC_SERVICE_REQUEST_REOPEN_LOG_FILES BIT_U32(1) uint32_t SCServiceTakeRequests(void); int SCRunningAsService(void);