From 2cd1c7c29ef4d2d3df3c5afd3ca6c788aede2bef Mon Sep 17 00:00:00 2001 From: Iain Patterson Date: Sun, 12 Jan 2014 23:56:10 +0000 Subject: [PATCH] Enable on-demand rotation. Running "nssm rotate " will send user-defined service control 128 to the service, triggering a rotation of output files after the next call to ReadFile(), regardless of the value of AppRotateBytes*. Note that since ReadFile() is synchronous, we have no way to interrupt it, hence there may be a significant delay before the rotation happens. --- README.txt | 12 +++++++++++- gui.cpp | 2 +- io.cpp | 13 ++++++++----- io.h | 1 + messages.mc | Bin 142580 -> 142790 bytes nssm.cpp | 1 + nssm.h | 3 +++ service.cpp | 7 +++++++ service.h | 8 ++++++-- 9 files changed, 38 insertions(+), 9 deletions(-) diff --git a/README.txt b/README.txt index 3769d4c..0affeb3 100644 --- a/README.txt +++ b/README.txt @@ -315,7 +315,17 @@ They will be rotated regardless of whether NSSM would otherwise have appended or replaced them. NSSM can also rotate files which hit the configured size threshold while the -service is running. To enable this feature, set AppRotateOnline to a non-zero +service is running. Additionally, you can trigger an on-demand rotation by +running the command + + nssm rotate + +On-demand rotations will happen after the next line of data is read from +the managed application, regardless of the value of AppRotateBytes. Be aware +that if the application is not particularly verbose the rotation may not +happen for some time. + +To enable online and on-demand rotation, set AppRotateOnline to a non-zero value. Note that online rotation requires NSSM to intercept the application's I/O diff --git a/gui.cpp b/gui.cpp index c09b363..64382f4 100644 --- a/gui.cpp +++ b/gui.cpp @@ -508,7 +508,7 @@ int configure(HWND window, nssm_service_t *service, nssm_service_t *orig_service /* Get rotation stuff. */ if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) { service->rotate_files = true; - if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->rotate_stdout_online = service->rotate_stderr_online = true; + if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->rotate_stdout_online = service->rotate_stderr_online = NSSM_ROTATE_ONLINE; check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, &service->rotate_seconds); check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low); } diff --git a/io.cpp b/io.cpp index 2602dc2..79848e9 100644 --- a/io.cpp +++ b/io.cpp @@ -242,7 +242,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { /* Try online rotation only if a size threshold is set. */ logger_t *stdout_logger = 0; - if (service->rotate_files && service->rotate_stdout_online && size.QuadPart) { + if (service->rotate_files && service->rotate_stdout_online) { stdout_logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t)); if (stdout_logger) { /* Pipe between application's stdout and our logging handle. */ @@ -256,6 +256,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { stdout_logger->write_handle = stdout_handle; stdout_logger->size = (__int64) size.QuadPart; stdout_logger->tid_ptr = &service->stdout_tid; + stdout_logger->rotate_online = &service->rotate_stdout_online; /* Logging thread. */ service->stdout_thread = create_logging_thread(stdout_logger); @@ -283,7 +284,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, error_string(GetLastError()), 0); return 4; } - service->rotate_stdout_online = false; + service->rotate_stdout_online = NSSM_ROTATE_OFFLINE; } set_flags = true; @@ -321,7 +322,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { /* Try online rotation only if a size threshold is set. */ logger_t *stderr_logger = 0; - if (service->rotate_files && service->rotate_stderr_online && size.QuadPart) { + if (service->rotate_files && service->rotate_stderr_online) { stderr_logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t)); if (stderr_logger) { /* Pipe between application's stderr and our logging handle. */ @@ -335,6 +336,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { stderr_logger->write_handle = stderr_handle; stderr_logger->size = (__int64) size.QuadPart; stderr_logger->tid_ptr = &service->stderr_tid; + stderr_logger->rotate_online = &service->rotate_stderr_online; /* Logging thread. */ service->stderr_thread = create_logging_thread(stderr_logger); @@ -362,7 +364,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDERR, error_string(GetLastError()), 0); return 7; } - service->rotate_stderr_online = false; + service->rotate_stderr_online = NSSM_ROTATE_OFFLINE; } } @@ -510,7 +512,7 @@ unsigned long WINAPI log_and_rotate(void *arg) { } else if (ret) continue; - if (size + (__int64) in >= logger->size) { + if (*logger->rotate_online == NSSM_ROTATE_ONLINE_ASAP || (logger->size && size + (__int64) in >= logger->size)) { /* Look for newline. */ unsigned long i; for (i = 0; i < in; i++) { @@ -527,6 +529,7 @@ unsigned long WINAPI log_and_rotate(void *arg) { size += (__int64) out; /* Rotate. */ + *logger->rotate_online = NSSM_ROTATE_ONLINE; TCHAR rotated[MAX_PATH]; rotated_filename(logger->path, rotated, _countof(rotated), 0); diff --git a/io.h b/io.h index 23c8488..60c3fd5 100644 --- a/io.h +++ b/io.h @@ -21,6 +21,7 @@ typedef struct { HANDLE write_handle; __int64 size; unsigned long *tid_ptr; + unsigned long *rotate_online; } logger_t; int get_createfile_parameters(HKEY, TCHAR *, TCHAR *, unsigned long *, unsigned long, unsigned long *, unsigned long, unsigned long *, unsigned long); diff --git a/messages.mc b/messages.mc index 68b52892589302db8cbbe03cf24a8418d7582d4f..d8f6f0eb137dc352a4404adb2b99b3f1af0a79ea 100644 GIT binary patch delta 100 zcmexzljGQJjtxK9Cl|2Ga2GM;Gn6nS0&(i(Kz8}fKiKDBm6-g4U21ZHsleua{AySg SG(Qn*ename, control, false); return ERROR_CALL_NOT_IMPLEMENTED; + + case NSSM_SERVICE_CONTROL_ROTATE: + log_service_control(service->name, control, true); + if (service->rotate_stdout_online) service->rotate_stdout_online = NSSM_ROTATE_ONLINE_ASAP; + if (service->rotate_stdout_online) service->rotate_stderr_online = NSSM_ROTATE_ONLINE_ASAP; + return NO_ERROR; } /* Unknown control */ diff --git a/service.h b/service.h index 8549fee..45680cf 100644 --- a/service.h +++ b/service.h @@ -28,6 +28,10 @@ #define NSSM_SHARE_INTERACTIVE_PROCESS NSSM_WIN32_SHARE_PROCESS _T("|") NSSM_INTERACTIVE_PROCESS #define NSSM_UNKNOWN _T("?") +#define NSSM_ROTATE_OFFLINE 0 +#define NSSM_ROTATE_ONLINE 1 +#define NSSM_ROTATE_ONLINE_ASAP 2 + typedef struct { bool native; TCHAR name[SERVICE_NAME_LENGTH]; @@ -68,8 +72,8 @@ typedef struct { HANDLE stderr_thread; unsigned long stderr_tid; bool rotate_files; - bool rotate_stdout_online; - bool rotate_stderr_online; + unsigned long rotate_stdout_online; + unsigned long rotate_stderr_online; unsigned long rotate_seconds; unsigned long rotate_bytes_low; unsigned long rotate_bytes_high; -- 2.7.4