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
NSSM 2.9.
[nssm.git]
/
service.cpp
diff --git
a/service.cpp
b/service.cpp
index
a400ebd
..
60a8db0
100644
(file)
--- a/
service.cpp
+++ b/
service.cpp
@@
-10,8
+10,9
@@
char exe[EXE_LENGTH];
char flags[CMD_LENGTH];
\r
char dir[MAX_PATH];
\r
bool stopping;
\r
char flags[CMD_LENGTH];
\r
char dir[MAX_PATH];
\r
bool stopping;
\r
-CRITICAL_SECTION throttle_section;
\r
-CONDITION_VARIABLE throttle_condition;
\r
+unsigned long throttle_delay;
\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
@@
-101,7
+102,7
@@
int install_service(char *name, char *exe, char *flags) {
fprintf(stderr, "The full path to " NSSM " is too long!\n");
\r
return 3;
\r
}
\r
fprintf(stderr, "The full path to " NSSM " is too long!\n");
\r
return 3;
\r
}
\r
- if (snprintf(command, sizeof(command), "\"%s\" %s", path, NSSM_RUN) < 0) {
\r
+ if (
_
snprintf(command, sizeof(command), "\"%s\" %s", path, NSSM_RUN) < 0) {
\r
fprintf(stderr, "Out of memory for ImagePath!\n");
\r
return 4;
\r
}
\r
fprintf(stderr, "Out of memory for ImagePath!\n");
\r
return 4;
\r
}
\r
@@
-199,7
+200,7
@@
void WINAPI service_main(unsigned long argc, char **argv) {
}
\r
\r
service_status.dwCurrentState = SERVICE_START_PENDING;
\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
SetServiceStatus(service_handle, &service_status);
\r
\r
/* Try to create the exit action parameters; we don't care if it fails */
\r
@@
-208,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
@@
-235,7
+239,7
@@
int monitor_service() {
int ret = start_service();
\r
if (ret) {
\r
char code[16];
\r
int ret = start_service();
\r
if (ret) {
\r
char code[16];
\r
- snprintf(code, sizeof(code), "%d", ret);
\r
+
_
snprintf(code, sizeof(code), "%d", ret);
\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_START_SERVICE_FAILED, exe, service_name, ret, 0);
\r
return ret;
\r
}
\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_START_SERVICE_FAILED, exe, service_name, ret, 0);
\r
return ret;
\r
}
\r
@@
-258,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
@@
-294,7
+300,7
@@
int start_service() {
ZeroMemory(&pi, sizeof(pi));
\r
\r
/* Get startup parameters */
\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
if (ret) {
\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, service_name, 0);
\r
return stop_service(2, true, true);
\r
@@
-321,7
+327,7
@@
int start_service() {
SetServiceStatus(service_handle, &service_status);
\r
\r
/* Wait for a clean startup. */
\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
\r
return 0;
\r
}
\r
@@
-449,16
+455,19
@@
void throttle_restart() {
if (throttle > 7) throttle = 8;
\r
\r
char threshold[8], milliseconds[8];
\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
_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