X-Git-Url: http://git.iain.cx/?a=blobdiff_plain;f=service.cpp;h=60a8db0b32cf43d9ca3cda01f6381754ad60e029;hb=b900e3b0859e71d5089c14314c0060082fc230de;hp=62926989e62d6b25ef7fc3c33e2c6c93a1e6f82c;hpb=f669237f05d127b88cd66d9dc2a32765ed6b2c23;p=nssm.git diff --git a/service.cpp b/service.cpp index 6292698..60a8db0 100644 --- a/service.cpp +++ b/service.cpp @@ -10,8 +10,9 @@ char exe[EXE_LENGTH]; char flags[CMD_LENGTH]; char dir[MAX_PATH]; bool stopping; -CRITICAL_SECTION throttle_section; -CONDITION_VARIABLE throttle_condition; +unsigned long throttle_delay; +HANDLE throttle_timer; +LARGE_INTEGER throttle_duetime; static enum { NSSM_EXIT_RESTART, NSSM_EXIT_IGNORE, NSSM_EXIT_REALLY, NSSM_EXIT_UNCLEAN } exit_actions; static const char *exit_action_strings[] = { "Restart", "Ignore", "Exit", "Suicide", 0 }; @@ -199,7 +200,7 @@ void WINAPI service_main(unsigned long argc, char **argv) { } service_status.dwCurrentState = SERVICE_START_PENDING; - service_status.dwWaitHint = NSSM_RESET_THROTTLE_RESTART + NSSM_WAITHINT_MARGIN; + service_status.dwWaitHint = throttle_delay + NSSM_WAITHINT_MARGIN; SetServiceStatus(service_handle, &service_status); /* Try to create the exit action parameters; we don't care if it fails */ @@ -208,7 +209,10 @@ void WINAPI service_main(unsigned long argc, char **argv) { set_service_recovery(service_name); /* Used for signalling a resume if the service pauses when throttled. */ - InitializeCriticalSection(&throttle_section); + throttle_timer = CreateWaitableTimer(0, 1, 0); + if (! throttle_timer) { + log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_CREATEWAITABLETIMER_FAILED, service_name, error_string(GetLastError()), 0); + } monitor_service(); } @@ -258,8 +262,10 @@ unsigned long WINAPI service_control_handler(unsigned long control, unsigned lon return NO_ERROR; case SERVICE_CONTROL_CONTINUE: + if (! throttle_timer) return ERROR_CALL_NOT_IMPLEMENTED; throttle = 0; - WakeConditionVariable(&throttle_condition); + ZeroMemory(&throttle_duetime, sizeof(throttle_duetime)); + SetWaitableTimer(throttle_timer, &throttle_duetime, 0, 0, 0, 0); service_status.dwCurrentState = SERVICE_CONTINUE_PENDING; service_status.dwWaitHint = throttle_milliseconds() + NSSM_WAITHINT_MARGIN; log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_RESET_THROTTLE, service_name, 0); @@ -294,7 +300,7 @@ int start_service() { ZeroMemory(&pi, sizeof(pi)); /* Get startup parameters */ - int ret = get_parameters(service_name, exe, sizeof(exe), flags, sizeof(flags), dir, sizeof(dir)); + int ret = get_parameters(service_name, exe, sizeof(exe), flags, sizeof(flags), dir, sizeof(dir), &throttle_delay); if (ret) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, service_name, 0); return stop_service(2, true, true); @@ -321,7 +327,7 @@ int start_service() { SetServiceStatus(service_handle, &service_status); /* Wait for a clean startup. */ - if (WaitForSingleObject(process_handle, NSSM_RESET_THROTTLE_RESTART) == WAIT_TIMEOUT) throttle = 0; + if (WaitForSingleObject(process_handle, throttle_delay) == WAIT_TIMEOUT) throttle = 0; return 0; } @@ -449,16 +455,19 @@ void throttle_restart() { if (throttle > 7) throttle = 8; char threshold[8], milliseconds[8]; - _snprintf(threshold, sizeof(threshold), "%d", NSSM_RESET_THROTTLE_RESTART); + _snprintf(threshold, sizeof(threshold), "%d", throttle_delay); _snprintf(milliseconds, sizeof(milliseconds), "%d", ms); log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_THROTTLED, service_name, threshold, milliseconds, 0); - EnterCriticalSection(&throttle_section); + if (throttle_timer) { + ZeroMemory(&throttle_duetime, sizeof(throttle_duetime)); + throttle_duetime.QuadPart = 0 - (ms * 10000LL); + SetWaitableTimer(throttle_timer, &throttle_duetime, 0, 0, 0, 0); + } service_status.dwCurrentState = SERVICE_PAUSED; SetServiceStatus(service_handle, &service_status); - SleepConditionVariableCS(&throttle_condition, &throttle_section, ms); - - LeaveCriticalSection(&throttle_section); + if (throttle_timer) WaitForSingleObject(throttle_timer, INFINITE); + else Sleep(ms); }