From 85fe241fc72957ceb77ed2c5587189a23246d87f Mon Sep 17 00:00:00 2001 From: Iain Patterson Date: Mon, 15 Dec 2014 14:05:55 +0000 Subject: [PATCH] Allow slow service startup again. Previously we enforced a maximum delay in reporting to the service manager that the service was started, and waited for the application to become unthrottled in the background. Users may prefer that the service not report a started state until the application is unthrottled. Therefore we now loop and increment the status checkpoint and wait hint to satisfy the service manager that we aren't hung. Thanks Tom Saul. --- service.cpp | 47 +++++++++++++++++++++++++++++++++++++---------- service.h | 1 + 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/service.cpp b/service.cpp index 52937cf..7e13da7 100644 --- a/service.cpp +++ b/service.cpp @@ -1394,6 +1394,7 @@ void WINAPI service_main(unsigned long argc, TCHAR **argv) { if (services) { service->handle = open_service(services, service->name, SERVICE_CHANGE_CONFIG, 0, 0); set_service_recovery(service); + CloseServiceHandle(services); } } @@ -1687,16 +1688,7 @@ int start_service(nssm_service_t *service) { but be mindful of the fact that we are blocking the service control manager so abandon the wait before too much time has elapsed. */ - unsigned long delay = service->throttle_delay; - if (delay > NSSM_SERVICE_STATUS_DEADLINE) { - TCHAR delay_milliseconds[16]; - _sntprintf_s(delay_milliseconds, _countof(delay_milliseconds), _TRUNCATE, _T("%lu"), delay); - TCHAR deadline_milliseconds[16]; - _sntprintf_s(deadline_milliseconds, _countof(deadline_milliseconds), _TRUNCATE, _T("%lu"), NSSM_SERVICE_STATUS_DEADLINE); - log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_STARTUP_DELAY_TOO_LONG, service->name, delay_milliseconds, NSSM, deadline_milliseconds, 0); - delay = NSSM_SERVICE_STATUS_DEADLINE; - } - unsigned long deadline = WaitForSingleObject(service->process_handle, delay); + await_startup(service); /* Signal successful start */ service->status.dwCurrentState = SERVICE_RUNNING; @@ -1985,3 +1977,38 @@ awaited: return ret; } + +int await_startup(nssm_service_t *service) { + unsigned long interval; + unsigned long waithint; + unsigned long waited; + + waithint = service->status.dwWaitHint; + waited = 0; + while (waited < service->throttle_delay) { + interval = service->throttle_delay - waited; + if (interval > NSSM_SERVICE_STATUS_DEADLINE) interval = NSSM_SERVICE_STATUS_DEADLINE; + + service->status.dwCurrentState = SERVICE_START_PENDING; + service->status.dwWaitHint += interval; + service->status.dwCheckPoint++; + SetServiceStatus(service->status_handle, &service->status); + + switch (WaitForSingleObject(service->process_handle, interval)) { + case WAIT_OBJECT_0: + return 1; + + case WAIT_TIMEOUT: + break; + + default: + return -1; + } + + waited += interval; + } + + service->throttle = 0; + + return 0; +} diff --git a/service.h b/service.h index c5a5d33..4ac3d6f 100644 --- a/service.h +++ b/service.h @@ -146,5 +146,6 @@ int stop_service(nssm_service_t *, unsigned long, bool, bool); void CALLBACK end_service(void *, unsigned char); void throttle_restart(nssm_service_t *); int await_shutdown(nssm_service_t *, TCHAR *, unsigned long); +int await_startup(nssm_service_t *); #endif -- 2.20.1