]> granicus.if.org Git - icinga2/commitdiff
Implement reload functionality for Windows
authorGunnar Beutner <gunnar@beutner.name>
Mon, 10 Aug 2015 13:28:10 +0000 (15:28 +0200)
committerMichael Friedrich <michael.friedrich@netways.de>
Fri, 4 Sep 2015 13:37:53 +0000 (15:37 +0200)
refs #7880
fixes #10051

CMakeLists.txt
icinga-app/icinga.cpp
lib/base/application.cpp

index 2723c432ccc0fdea81e25fbaf8c2c305c66db575..1f0e6c19b04544ee798cd0142d9bdd6b6137c5f8 100644 (file)
@@ -228,7 +228,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'")
index 52bba4765ca1d78c1789201160412ba1ea5c8de5..c82a517fea2881a9d44de8e6ecec73bdada99728 100644 (file)
@@ -45,8 +45,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<String> GetLogLevelCompletionSuggestions(const String& arg)
@@ -606,7 +607,7 @@ VOID WINAPI ServiceControlHandler(DWORD dwCtrl)
 {
        if (dwCtrl == SERVICE_CONTROL_STOP) {
                ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
-               Application::RequestShutdown();
+               TerminateJobObject(l_Job, 0);
        }
 }
 
@@ -621,11 +622,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 */
 
index 81c8efaa8b0d08b789676bfd6bac787ebf0f744d..84a5616e365c74c27cb0214a866b5e168717af69 100644 (file)
@@ -327,11 +327,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)
@@ -348,8 +359,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);