Skip to content

Commit ee9a86c

Browse files
author
Iain Patterson
committedSep 5, 2016
Ensure logging threads exit.
We need to close all handles to ensure that all logging threads are joined. Care must be taken to close the writing end of the logging pipe first so that the logging thread can issue a final ReadFile() call. Before the thread exits it should close the reading end, however as a safety measure we WaitForSingleObject() then close the reading end from the main rotation thread.
1 parent aecb56a commit ee9a86c

File tree

4 files changed

+25
-0
lines changed

4 files changed

+25
-0
lines changed
 

‎io.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,24 @@ void close_output_handles(STARTUPINFO *si) {
428428
if (si->hStdError) CloseHandle(si->hStdError);
429429
}
430430

431+
void cleanup_loggers(nssm_service_t *service) {
432+
unsigned long interval = NSSM_CLEANUP_LOGGERS_DEADLINE;
433+
HANDLE thread_handle = INVALID_HANDLE_VALUE;
434+
435+
close_handle(&service->stdout_thread, &thread_handle);
436+
/* Close write end of the data pipe so logging thread can finalise read. */
437+
close_handle(&service->stdout_si);
438+
/* Await logging thread then close read end. */
439+
if (thread_handle != INVALID_HANDLE_VALUE) WaitForSingleObject(thread_handle, interval);
440+
close_handle(&service->stdout_pipe);
441+
442+
thread_handle = INVALID_HANDLE_VALUE;
443+
close_handle(&service->stderr_thread, &thread_handle);
444+
close_handle(&service->stderr_si);
445+
if (thread_handle != INVALID_HANDLE_VALUE) WaitForSingleObject(thread_handle, interval);
446+
close_handle(&service->stderr_pipe);
447+
}
448+
431449
/*
432450
Try multiple times to read from a file.
433451
Returns: 0 on success.

‎io.h

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ void rotate_file(TCHAR *, TCHAR *, unsigned long, unsigned long, unsigned long,
3838
int get_output_handles(nssm_service_t *, STARTUPINFO *);
3939
int use_output_handles(nssm_service_t *, STARTUPINFO *);
4040
void close_output_handles(STARTUPINFO *);
41+
void cleanup_loggers(nssm_service_t *);
4142
unsigned long WINAPI log_and_rotate(void *);
4243

4344
#endif

‎nssm.h

+3
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,7 @@ const TCHAR *nssm_exe();
156156
/* How many milliseconds to wait for outstanding hooks. */
157157
#define NSSM_HOOK_THREAD_DEADLINE 80000
158158

159+
/* How many milliseconds to wait for closing logging thread. */
160+
#define NSSM_CLEANUP_LOGGERS_DEADLINE 1500
161+
159162
#endif

‎service.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,9 @@ void CALLBACK end_service(void *arg, unsigned char why) {
20602060
service->exit_count++;
20612061
(void) nssm_hook(&hook_threads, service, NSSM_HOOK_EVENT_EXIT, NSSM_HOOK_ACTION_POST, NULL, NSSM_HOOK_DEADLINE, true);
20622062

2063+
/* Exit logging threads. */
2064+
cleanup_loggers(service);
2065+
20632066
/*
20642067
The why argument is true if our wait timed out or false otherwise.
20652068
Our wait is infinite so why will never be true when called by the system.

0 commit comments

Comments
 (0)
Please sign in to comment.