in erts/etc/win32/erlsrv/erlsrv_service.c [707:966]
static VOID WINAPI service_main_loop(DWORD argc, wchar_t **argv){
int waithint = 30000;
int checkpoint = 1;
RegEntry *keys;
RegEntry *save_keys;
ServerInfo srvi;
HANDLE harr[2];
FILETIME creationt,exitt,kernelt,usert;
LONGLONG creationl,exitl,diffl;
wchar_t event_name[MAX_PATH] = L"ErlSrv_";
wchar_t executable_name[MAX_PATH];
#ifdef DEBUG
wchar_t errorbuff[2048]; /* FIXME... */
#endif
int success_wait = NO_SUCCESS_WAIT;
real_service_name = argv[0];
if(!pull_service_name()){
log_error(L"Could not get Display name of erlang service.");
set_stopped(ERROR_CANTREAD);
return;
}
SetEnvironmentVariableW(SERVICE_ENV, service_name);
wcsncat(event_name, service_name, MAX_PATH - wcslen(event_name));
event_name[MAX_PATH - 1] = L'\0';
if(!GetModuleFileNameW(NULL, executable_name, MAX_PATH)){
log_error(L"Unable to retrieve module file name, " EXECUTABLE_ENV
L" will not be set.");
} else {
wchar_t quoted_exe_name[MAX_PATH+4];
swprintf(quoted_exe_name, MAX_PATH+4, L"\"%s\"", executable_name);
SetEnvironmentVariableW(EXECUTABLE_ENV, quoted_exe_name);
}
log_debug(L"Here we go, service_main_loop...");
currentState = SERVICE_START_PENDING;
InitializeCriticalSection(&crit);
eventStop = CreateEvent(NULL,FALSE,FALSE,NULL);
if ((eventKillErlang = create_erlang_event(event_name)) != NULL) {
srvi.event_name = event_name;
} else {
srvi.event_name = NULL;
}
statusHandle = RegisterServiceCtrlHandlerW(real_service_name, &handler);
if(!statusHandle)
return;
set_start_pending(waithint,checkpoint);
keys = get_keys(service_name);
if(!keys){
log_error(L"Could not get registry keys for erlang service.");
set_stopped(ERROR_CANTREAD);
return;
}
srvi.keys = keys;
srvi.erl_stdin = NULL;
++checkpoint;
if(!start_a_service(&srvi)){
log_error(L"Could not start erlang machine");
set_stopped(ERROR_PROCESS_ABORTED);
if (eventKillErlang != NULL) {
CloseHandle(eventKillErlang);
}
free_keys(keys);
return;
}
set_start_pending(waithint,checkpoint);
set_running();
success_wait = INITIAL_SUCCESS_WAIT;
harr[0] = srvi.info.hProcess;
harr[1] = eventStop;
for(;;){
DWORD ret;
ret = WaitForMultipleObjects((DWORD) 2,
harr,
FALSE,
(success_wait == NO_SUCCESS_WAIT) ?
INFINITE :
SUCCESS_WAIT_TIME);
if(ret == WAIT_TIMEOUT){
/* Just do the "success reporting" and continue */
if(success_wait == INITIAL_SUCCESS_WAIT){
log_info(L"Erlang service started successfully.");
} else {
log_warning(L"Erlang service restarted");
}
success_wait = NO_SUCCESS_WAIT;
continue;
}
if(ret == WAIT_FAILED || (int)(ret-WAIT_OBJECT_0) >= 2){
set_stopped(WAIT_FAILED);
log_error(L"Internal error, could not wait for objects.");
if (eventKillErlang != NULL) {
CloseHandle(eventKillErlang);
}
free_keys(keys);
return;
}
ret -= WAIT_OBJECT_0;
if(((int) ret) == 1){
/* Stop service... */
checkpoint = 2; /* 1 is taken by the handler */
set_stop_pending(waithint,checkpoint);
if(stop_erlang(&srvi,waithint,&checkpoint)){
log_debug(L"Erlang machine is stopped");
CloseHandle(eventStop);
if (eventKillErlang != NULL) {
CloseHandle(eventKillErlang);
}
set_stopped(NO_ERROR);
if(srvi.erl_stdin)
CloseHandle(srvi.erl_stdin);
free_keys(keys);
return;
} else {
log_warning(L"Unable to stop erlang service.");
set_running();
continue;
}
}
/* Reload the registry keys, they may have changed. */
save_keys = keys;
keys = get_keys(service_name);
if(!keys){
log_error(L"Could not reload registry keys.");
keys = srvi.keys = save_keys;
} else {
#ifdef HARDDEBUG
swprintf(errorbuff,2048,L"Reloaded the registry keys because %s stopped.",
service_name);
log_debug(errorbuff);
#endif /* HARDDEBUG */
free_keys(save_keys);
srvi.keys = keys;
}
if(srvi.keys[OnFail].data.value == ON_FAIL_RESTART ||
srvi.keys[OnFail].data.value == ON_FAIL_RESTART_ALWAYS){
if(!GetProcessTimes(srvi.info.hProcess,&creationt,
&exitt,&kernelt,&usert)){
DWORD rcode = GetLastError();
log_error(L"Could not get process time of terminated process.");
CloseHandle(srvi.info.hProcess);
CloseHandle(srvi.info.hThread);
CloseHandle(eventStop);
if(srvi.erl_stdin)
CloseHandle(srvi.erl_stdin);
set_stopped(rcode);
if (eventKillErlang != NULL) {
CloseHandle(eventKillErlang);
}
free_keys(keys);
return;
}
CloseHandle(srvi.info.hProcess);
CloseHandle(srvi.info.hThread);
if(srvi.erl_stdin)
CloseHandle(srvi.erl_stdin);
srvi.erl_stdin = NULL;
memcpy(&creationl,&creationt,sizeof(FILETIME));
memcpy(&exitl,&exitt,sizeof(FILETIME));
diffl = exitl - creationl;
diffl /= 10000000;
#ifdef DEBUG
swprintf(errorbuff,2048,L"Process lived for %d seconds", (int) diffl);
log_debug(errorbuff);
#endif
if(diffl > CYCLIC_RESTART_LIMIT ||
srvi.keys[OnFail].data.value == ON_FAIL_RESTART_ALWAYS){
if(!start_a_service(&srvi)){
log_error(L"Unable to restart failed erlang service, aborting.");
CloseHandle(eventStop);
set_stopped(ERROR_PROCESS_ABORTED);
if (eventKillErlang != NULL) {
CloseHandle(eventKillErlang);
}
free_keys(keys);
return;
}
log_warning(L"Restarted erlang machine.");
if(diffl <= CYCLIC_RESTART_LIMIT)
log_warning(L"Possible cyclic restarting of erlang machine.");
success_wait = RESTART_SUCCESS_WAIT;
harr[0] = srvi.info.hProcess;
} else {
if(success_wait == INITIAL_SUCCESS_WAIT){
log_error(L"Erlang machine stopped instantly "
L"(distribution name conflict?). "
L"The service is not restarted, ignoring OnFail option.");
} else {
log_error(L"Erlang machine seems to die "
L"continously, not restarted.");
}
CloseHandle(eventStop);
set_stopped(ERROR_PROCESS_ABORTED);
if (eventKillErlang != NULL) {
CloseHandle(eventKillErlang);
}
free_keys(keys);
return;
}
} else if(srvi.keys[OnFail].data.value == ON_FAIL_REBOOT){
log_error(L"Rebooting because erlang machine stopped.");
enable_privilege();
if(!InitiateSystemShutdown("",NULL,0,TRUE,TRUE)){
log_error(L"Failed to reboot!");
#ifdef HARDDEBUG
{
wchar_t *mes;
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &mes,
0,
NULL );
log_debug(mes);
LocalFree(mes);
}
#endif
CloseHandle(srvi.info.hProcess);
CloseHandle(eventStop);
if(srvi.erl_stdin != NULL)
CloseHandle(srvi.erl_stdin);
set_stopped(NO_ERROR);
if (eventKillErlang != NULL) {
CloseHandle(eventKillErlang);
}
free_keys(keys);
return;
}
} else {
DWORD ecode = NO_ERROR;
if(success_wait == NO_SUCCESS_WAIT){
log_warning(L"Erlang machine voluntarily stopped. "
L"The service is not restarted as OnFail "
L"is set to ignore.");
} else {
log_error(L"Erlang machine stopped instantly "
L"(distribution name conflict?). "
L"The service is not restarted as OnFail is set to ignore.");
ecode = ERROR_PROCESS_ABORTED;
}
CloseHandle(srvi.info.hProcess);
CloseHandle(eventStop);
if(srvi.erl_stdin != NULL)
CloseHandle(srvi.erl_stdin);
set_stopped(ecode);
if (eventKillErlang != NULL) {
CloseHandle(eventKillErlang);
}
free_keys(keys);
return;
}
}
}