From: Gunnar Beutner Date: Mon, 10 Aug 2015 13:28:10 +0000 (+0200) Subject: Implement reload functionality for Windows X-Git-Tag: v2.4.0~438 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7890e20da7ddd0383cdfbdb19da4acc4ab5b39cd;p=icinga2 Implement reload functionality for Windows fixes #7880 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index fbe631c30..bb9e35f37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -259,7 +259,6 @@ set(CPACK_NSIS_EXECUTABLES_DIRECTORY "sbin") set(CPACK_PACKAGE_EXECUTABLES "Icinga2SetupAgent;Icinga 2 Agent Wizard") set(CPACK_NSIS_MUI_FINISHPAGE_RUN "Icinga2SetupAgent") set(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS "nsExec::Exec 'net stop icinga2'") -set(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS "${CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS}\nSleep 10000") set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}\nnsExec::Exec 'icacls \\\"$INSTDIR\\\" /grant NetworkService:(oi)(ci)m'") set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}\nnsExec::Exec 'icacls \\\"$INSTDIR\\\\etc\\\" /inheritance:r /grant:r NetworkService:(oi)(ci)m /grant:r Administrators:(oi)(ci)f'") set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}\nCreateDirectory '$INSTDIR\\\\etc\\\\icinga2\\\\pki'") diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index de270bc0f..9810d3a7c 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -46,8 +46,9 @@ using namespace icinga; namespace po = boost::program_options; #ifdef _WIN32 -SERVICE_STATUS l_SvcStatus; -SERVICE_STATUS_HANDLE l_SvcStatusHandle; +static SERVICE_STATUS l_SvcStatus; +static SERVICE_STATUS_HANDLE l_SvcStatusHandle; +static HANDLE l_Job; #endif /* _WIN32 */ static std::vector GetLogLevelCompletionSuggestions(const String& arg) @@ -626,7 +627,7 @@ VOID WINAPI ServiceControlHandler(DWORD dwCtrl) { if (dwCtrl == SERVICE_CONTROL_STOP) { ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); - Application::RequestShutdown(); + TerminateJobObject(l_Job, 0); } } @@ -641,11 +642,58 @@ VOID WINAPI ServiceMain(DWORD argc, LPSTR *argv) ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); - int rc = Main(); + l_Job = CreateJobObject(NULL, NULL); - ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, rc); + for (;;) { + LPSTR arg = argv[0]; + String args; + int uargc = Application::GetArgC(); + char **uargv = Application::GetArgV(); - Application::Exit(rc); + args += Utility::EscapeShellArg(Application::GetExePath(uargv[0])); + + for (int i = 2; i < uargc && uargv[i]; i++) { + if (args != "") + args += " "; + + args += Utility::EscapeShellArg(uargv[i]); + } + + STARTUPINFO si = { sizeof(si) }; + PROCESS_INFORMATION pi; + + char *uargs = strdup(args.CStr()); + + BOOL res = CreateProcess(NULL, uargs, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + + free(uargs); + + if (!res) + break; + + CloseHandle(pi.hThread); + + AssignProcessToJobObject(l_Job, pi.hProcess); + + if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) + break; + + DWORD exitStatus; + + if (!GetExitCodeProcess(pi.hProcess, &exitStatus)) + break; + + if (exitStatus != 7) + break; + } + + TerminateJobObject(l_Job, 0); + + CloseHandle(l_Job); + + ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); + + Application::Exit(0); } #endif /* _WIN32 */ diff --git a/lib/base/application.cpp b/lib/base/application.cpp index b32ea4fb8..435a8c655 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -329,11 +329,22 @@ void Application::OnShutdown(void) /* Nothing to do here. */ } -static void ReloadProcessCallback(const ProcessResult& pr) +static void ReloadProcessCallbackInternal(const ProcessResult& pr) { if (pr.ExitStatus != 0) Log(LogCritical, "Application", "Found error in config: reloading aborted"); +#ifdef _WIN32 + else + Application::Exit(7); /* keep this exit code in sync with icinga-app */ +#endif /* _WIN32 */ +} + +static void ReloadProcessCallback(const ProcessResult& pr) +{ l_Restarting = false; + + boost::thread t(boost::bind(&ReloadProcessCallbackInternal, pr)); + t.detach(); } pid_t Application::StartReloadProcess(void) @@ -350,8 +361,13 @@ pid_t Application::StartReloadProcess(void) else i++; // the next parameter after --reload-internal is the pid, remove that too } + +#ifndef _WIN32 args->Add("--reload-internal"); args->Add(Convert::ToString(Utility::GetPid())); +#else /* _WIN32 */ + args->Add("--validate"); +#endif /* _WIN32 */ Process::Ptr process = new Process(Process::PrepareCommand(args)); process->SetTimeout(300);