git://git.iain.cx/iain
/
nssm.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Timer safety.
[nssm.git]
/
service.cpp
diff --git
a/service.cpp
b/service.cpp
index
283cbea
..
60a8db0
100644
(file)
--- a/
service.cpp
+++ b/
service.cpp
@@
-11,8
+11,8
@@
char flags[CMD_LENGTH];
char dir[MAX_PATH];
\r
bool stopping;
\r
unsigned long throttle_delay;
\r
char dir[MAX_PATH];
\r
bool stopping;
\r
unsigned long throttle_delay;
\r
-
CRITICAL_SECTION throttle_section
;
\r
-
CONDITION_VARIABLE throttle_condition
;
\r
+
HANDLE throttle_timer
;
\r
+
LARGE_INTEGER throttle_duetime
;
\r
\r
static enum { NSSM_EXIT_RESTART, NSSM_EXIT_IGNORE, NSSM_EXIT_REALLY, NSSM_EXIT_UNCLEAN } exit_actions;
\r
static const char *exit_action_strings[] = { "Restart", "Ignore", "Exit", "Suicide", 0 };
\r
\r
static enum { NSSM_EXIT_RESTART, NSSM_EXIT_IGNORE, NSSM_EXIT_REALLY, NSSM_EXIT_UNCLEAN } exit_actions;
\r
static const char *exit_action_strings[] = { "Restart", "Ignore", "Exit", "Suicide", 0 };
\r
@@
-209,7
+209,10
@@
void WINAPI service_main(unsigned long argc, char **argv) {
set_service_recovery(service_name);
\r
\r
/* Used for signalling a resume if the service pauses when throttled. */
\r
set_service_recovery(service_name);
\r
\r
/* Used for signalling a resume if the service pauses when throttled. */
\r
- InitializeCriticalSection(&throttle_section);
\r
+ throttle_timer = CreateWaitableTimer(0, 1, 0);
\r
+ if (! throttle_timer) {
\r
+ log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_CREATEWAITABLETIMER_FAILED, service_name, error_string(GetLastError()), 0);
\r
+ }
\r
\r
monitor_service();
\r
}
\r
\r
monitor_service();
\r
}
\r
@@
-259,8
+262,10
@@
unsigned long WINAPI service_control_handler(unsigned long control, unsigned lon
return NO_ERROR;
\r
\r
case SERVICE_CONTROL_CONTINUE:
\r
return NO_ERROR;
\r
\r
case SERVICE_CONTROL_CONTINUE:
\r
+ if (! throttle_timer) return ERROR_CALL_NOT_IMPLEMENTED;
\r
throttle = 0;
\r
throttle = 0;
\r
- WakeConditionVariable(&throttle_condition);
\r
+ ZeroMemory(&throttle_duetime, sizeof(throttle_duetime));
\r
+ SetWaitableTimer(throttle_timer, &throttle_duetime, 0, 0, 0, 0);
\r
service_status.dwCurrentState = SERVICE_CONTINUE_PENDING;
\r
service_status.dwWaitHint = throttle_milliseconds() + NSSM_WAITHINT_MARGIN;
\r
log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_RESET_THROTTLE, service_name, 0);
\r
service_status.dwCurrentState = SERVICE_CONTINUE_PENDING;
\r
service_status.dwWaitHint = throttle_milliseconds() + NSSM_WAITHINT_MARGIN;
\r
log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_RESET_THROTTLE, service_name, 0);
\r
@@
-454,12
+459,15
@@
void throttle_restart() {
_snprintf(milliseconds, sizeof(milliseconds), "%d", ms);
\r
log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_THROTTLED, service_name, threshold, milliseconds, 0);
\r
\r
_snprintf(milliseconds, sizeof(milliseconds), "%d", ms);
\r
log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_THROTTLED, service_name, threshold, milliseconds, 0);
\r
\r
- EnterCriticalSection(&throttle_section);
\r
+ if (throttle_timer) {
\r
+ ZeroMemory(&throttle_duetime, sizeof(throttle_duetime));
\r
+ throttle_duetime.QuadPart = 0 - (ms * 10000LL);
\r
+ SetWaitableTimer(throttle_timer, &throttle_duetime, 0, 0, 0, 0);
\r
+ }
\r
\r
service_status.dwCurrentState = SERVICE_PAUSED;
\r
SetServiceStatus(service_handle, &service_status);
\r
\r
\r
service_status.dwCurrentState = SERVICE_PAUSED;
\r
SetServiceStatus(service_handle, &service_status);
\r
\r
- SleepConditionVariableCS(&throttle_condition, &throttle_section, ms);
\r
-
\r
- LeaveCriticalSection(&throttle_section);
\r
+ if (throttle_timer) WaitForSingleObject(throttle_timer, INFINITE);
\r
+ else Sleep(ms);
\r
}
\r
}
\r