(where the service will be shown in Paused state) to send a continue signal to\r
NSSM and it will retry within a few seconds.\r
\r
+By default, NSSM defines "a timely manner" to be within 1500 milliseconds.\r
+You can change the threshold for the service by setting the number of\r
+milliseconds as a REG_DWORD value in the registry at\r
+HKLM\SYSTEM\CurrentControlSet\Services\<service>\Parameters\AppThrottle.\r
+\r
NSSM will look in the registry under\r
HKLM\SYSTEM\CurrentControlSet\Services\<service>\Parameters\AppExit for\r
string (REG_EXPAND_SZ) values corresponding to the exit code of the application.\r
Request to resume service %1. Throttling of restart attempts will be reset.
.
+MessageId = +1
+SymbolicName = NSSM_EVENT_BOGUS_THROTTLE
+Severity = Warning
+Language = English
+The registry value %2, used to specify the minimum number of milliseconds which must elapse before service %1 is considered to have started successfully, was not of type REG_DWORD. The default time of %3 milliseconds will be used.
+.
+
\r
/*\r
Throttle the restart of the service if it stops before this many\r
- milliseconds have elapsed since startup.\r
+ milliseconds have elapsed since startup. Override in registry.\r
*/\r
#define NSSM_RESET_THROTTLE_RESTART 1500\r
\r
return 0;\r
}\r
\r
-int get_parameters(char *service_name, char *exe, int exelen, char *flags, int flagslen, char *dir, int dirlen) {\r
+int get_parameters(char *service_name, char *exe, int exelen, char *flags, int flagslen, char *dir, int dirlen, unsigned long *throttle_delay) {\r
+ unsigned long ret;\r
+\r
/* Get registry */\r
char registry[KEY_LENGTH];\r
if (_snprintf(registry, sizeof(registry), NSSM_REGISTRY, service_name) < 0) {\r
}\r
else {\r
/* Help! */\r
- unsigned long ret = GetWindowsDirectory(dir, dirlen);\r
+ ret = GetWindowsDirectory(dir, dirlen);\r
if (! ret || ret > dirlen) {\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_NO_DIR_AND_NO_FALLBACK, NSSM_REG_DIR, service_name, 0);\r
RegCloseKey(key);\r
log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_NO_DIR, NSSM_REG_DIR, service_name, dir, 0);\r
}\r
\r
+ /* Try to get throttle restart delay */\r
+ unsigned long type = REG_DWORD;\r
+ unsigned long buflen = sizeof(*throttle_delay);\r
+ bool throttle_ok = false;\r
+ ret = RegQueryValueEx(key, NSSM_REG_THROTTLE, 0, &type, (unsigned char *) throttle_delay, &buflen);\r
+ if (ret != ERROR_SUCCESS) {\r
+ if (ret != ERROR_FILE_NOT_FOUND) {\r
+ if (type != REG_DWORD) {\r
+ char milliseconds[16];\r
+ _snprintf(milliseconds, sizeof(milliseconds), "%lu", NSSM_RESET_THROTTLE_RESTART);\r
+ log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_BOGUS_THROTTLE, service_name, NSSM_REG_THROTTLE, milliseconds, 0);\r
+ }\r
+ else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_THROTTLE, error_string(GetLastError()), 0);\r
+ }\r
+ }\r
+ else throttle_ok = true;\r
+\r
+ if (! throttle_ok) *throttle_delay = NSSM_RESET_THROTTLE_RESTART;\r
+\r
/* Close registry */\r
RegCloseKey(key);\r
\r
#define NSSM_REG_FLAGS "AppParameters"\r
#define NSSM_REG_DIR "AppDirectory"\r
#define NSSM_REG_EXIT "AppExit"\r
+#define NSSM_REG_THROTTLE "AppThrottle"\r
\r
int create_messages();\r
int create_parameters(char *, char *, char *, char *);\r
int create_exit_action(char *, const char *);\r
int expand_parameter(HKEY, char *, char *, unsigned long, bool);\r
-int get_parameters(char *, char *, int, char *, int, char *, int);\r
+int get_parameters(char *, char *, int, char *, int, char *, int, unsigned long *);\r
int get_exit_action(char *, unsigned long *, unsigned char *, bool *);\r
\r
#endif\r
char flags[CMD_LENGTH];\r
char dir[MAX_PATH];\r
bool stopping;\r
+unsigned long throttle_delay;\r
CRITICAL_SECTION throttle_section;\r
CONDITION_VARIABLE throttle_condition;\r
\r
}\r
\r
service_status.dwCurrentState = SERVICE_START_PENDING;\r
- service_status.dwWaitHint = NSSM_RESET_THROTTLE_RESTART + NSSM_WAITHINT_MARGIN;\r
+ service_status.dwWaitHint = throttle_delay + NSSM_WAITHINT_MARGIN;\r
SetServiceStatus(service_handle, &service_status);\r
\r
/* Try to create the exit action parameters; we don't care if it fails */\r
ZeroMemory(&pi, sizeof(pi));\r
\r
/* Get startup parameters */\r
- int ret = get_parameters(service_name, exe, sizeof(exe), flags, sizeof(flags), dir, sizeof(dir));\r
+ int ret = get_parameters(service_name, exe, sizeof(exe), flags, sizeof(flags), dir, sizeof(dir), &throttle_delay);\r
if (ret) {\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, service_name, 0);\r
return stop_service(2, true, true);\r
SetServiceStatus(service_handle, &service_status);\r
\r
/* Wait for a clean startup. */\r
- if (WaitForSingleObject(process_handle, NSSM_RESET_THROTTLE_RESTART) == WAIT_TIMEOUT) throttle = 0;\r
+ if (WaitForSingleObject(process_handle, throttle_delay) == WAIT_TIMEOUT) throttle = 0;\r
\r
return 0;\r
}\r
if (throttle > 7) throttle = 8;\r
\r
char threshold[8], milliseconds[8];\r
- _snprintf(threshold, sizeof(threshold), "%d", NSSM_RESET_THROTTLE_RESTART);\r
+ _snprintf(threshold, sizeof(threshold), "%d", throttle_delay);\r
_snprintf(milliseconds, sizeof(milliseconds), "%d", ms);\r
log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_THROTTLED, service_name, threshold, milliseconds, 0);\r
\r