Enforce maximum report delay when starting service.

We were not changing the service's state to running until the restart
throttling threshold had passed.  However best practice is to change the
status to running or stopped as quickly as possible.  Therefore we we
now report the status after no more than 20000 milliseconds regardless
of the throttle setting.
master
Iain Patterson 11 years ago
parent da1b8e1cb0
commit 98a2516c22

@ -1376,3 +1376,16 @@ Language = Italian
Chiamata a CreateThread() fallita:
%1
.
MessageId = +1
SymbolicName = NSSM_EVENT_STARTUP_DELAY_TOO_LONG
Severity = Informational
Language = English
The minimum number of milliseconds which must pass before service %1 is considered to have been started successfully is set to %2. Access to the Windows service control manager is blocked until the service updates its status, therefore %3 will wait a maximum of %4 milliseconds before reporting the service's state as running. Service restart throttling will be enforced if the service runs for less than the full %2 milliseconds.
.
Language = French
The minimum number of milliseconds which must pass before service %1 is considered to have been started successfully is set to %2. Access to the Windows service control manager is blocked until the service updates its status, therefore %3 will wait a maximum of %4 milliseconds before reporting the service's state as running. Service restart throttling will be enforced if the service runs for less than the full %2 milliseconds.
.
Language = Italian
The minimum number of milliseconds which must pass before service %1 is considered to have been started successfully is set to %2. Access to the Windows service control manager is blocked until the service updates its status, therefore %3 will wait a maximum of %4 milliseconds before reporting the service's state as running. Service restart throttling will be enforced if the service runs for less than the full %2 milliseconds.
.

@ -67,6 +67,6 @@ int str_equiv(const char *, const char *);
#define NSSM_STOP_METHOD_TERMINATE (1 << 3)
/* How many milliseconds to wait before updating service status. */
#define NSSM_SHUTDOWN_CHECKPOINT 20000
#define NSSM_SERVICE_STATUS_DEADLINE 20000
#endif

@ -450,13 +450,34 @@ int start_service() {
close_output_handles(&si);
/* Wait for a clean startup. */
if (WaitForSingleObject(process_handle, throttle_delay) == WAIT_TIMEOUT) throttle = 0;
/*
Wait for a clean startup before changing the service status to RUNNING
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 = throttle_delay;
if (delay > NSSM_SERVICE_STATUS_DEADLINE) {
char delay_milliseconds[16];
_snprintf_s(delay_milliseconds, sizeof(delay_milliseconds), _TRUNCATE, "%lu", delay);
char deadline_milliseconds[16];
_snprintf_s(deadline_milliseconds, sizeof(deadline_milliseconds), _TRUNCATE, "%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(process_handle, delay);
/* Signal successful start */
service_status.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(service_handle, &service_status);
/* Continue waiting for a clean startup. */
if (deadline == WAIT_TIMEOUT) {
if (throttle_delay > delay) {
if (WaitForSingleObject(process_handle, throttle_delay - delay) == WAIT_TIMEOUT) throttle = 0;
}
else throttle = 0;
}
return 0;
}
@ -639,9 +660,10 @@ void throttle_restart() {
time dwCheckPoint is also increased.
Our strategy then is to retrieve the initial dwWaitHint and wait for
NSSM_SHUTDOWN_CHECKPOINT milliseconds. If the process is still running and
we haven't finished waiting we increment dwCheckPoint and add whichever is
smaller of NSSM_SHUTDOWN_CHECKPOINT or the remaining timeout to dwWaitHint.
NSSM_SERVICE_STATUS_DEADLINE milliseconds. If the process is still running
and we haven't finished waiting we increment dwCheckPoint and add whichever is
smaller of NSSM_SERVICE_STATUS_DEADLINE or the remaining timeout to
dwWaitHint.
Only doing both these things will prevent the system from killing the service.
@ -672,7 +694,7 @@ int await_shutdown(char *function_name, char *service_name, SERVICE_STATUS_HANDL
waited = 0;
while (waited < timeout) {
interval = timeout - waited;
if (interval > NSSM_SHUTDOWN_CHECKPOINT) interval = NSSM_SHUTDOWN_CHECKPOINT;
if (interval > NSSM_SERVICE_STATUS_DEADLINE) interval = NSSM_SERVICE_STATUS_DEADLINE;
service_status->dwCurrentState = SERVICE_STOP_PENDING;
service_status->dwWaitHint += interval;

Loading…
Cancel
Save