]> granicus.if.org Git - icinga2/commitdiff
Proof of concept how a real reload-handling with systemd could work.
authorGerd von Egidy <gerd@egidy.de>
Sat, 17 May 2014 21:07:10 +0000 (23:07 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Sun, 18 May 2014 16:39:35 +0000 (18:39 +0200)
Refs #6118

icinga-app/icinga.cpp
lib/base/application.cpp
lib/base/application.h
lib/base/process.cpp
lib/base/process.h

index 666ae0c0c92a014fe6b18c2fc9fd54e250c38486..05d359d773032f8f895b98d35c7b5ef6a948a2be 100644 (file)
@@ -169,8 +169,11 @@ static bool Daemonize(const String& stderrFile)
                return false;
        }
 
-       if (pid)
+       if (pid) {
+               // TODO: do a real wait till the pidfile is written by the daemon
+               Utility::Sleep(5);
                exit(0);
+       }
 
        int fdnull = open("/dev/null", O_RDWR);
        if (fdnull >= 0) {
@@ -483,7 +486,7 @@ int Main(void)
                Log(LogInformation, "icinga-app", "Previous instance has ended, taking over now.");
        }
 
-       if (g_AppParams.count("daemonize")) {
+       if (g_AppParams.count("daemonize") && !g_AppParams.count("reload-internal")) {
                String errorLog;
 
                if (g_AppParams.count("errorlog"))
index 4b8672958f9f1d634e6d08b9b810dce64eed433e..4dca020280b2fa6cd6cd5b23f504ad6886fcc192 100644 (file)
@@ -46,6 +46,7 @@ REGISTER_TYPE(Application);
 Application *Application::m_Instance = NULL;
 bool Application::m_ShuttingDown = false;
 bool Application::m_RequestRestart = false;
+pid_t Application::m_ReloadProcess = 0;
 static bool l_Restarting = false;
 bool Application::m_Debugging = false;
 int Application::m_ArgC;
@@ -91,6 +92,13 @@ void Application::Stop(void)
        WSACleanup();
 #endif /* _WIN32 */
 
+       // Getting a shutdown-signal when a restart is in progress usually
+       // means that the restart succeeded and the new process wants to take
+       // over. Write the PID of the new process to the pidfile before this
+       // process exits to keep systemd happy.
+       if (l_Restarting)
+               UpdatePidFile(GetPidPath(),m_ReloadProcess);
+
        ClosePidFile();
 
        DynamicObject::Stop();
@@ -218,7 +226,7 @@ void Application::SetArgV(char **argv)
  * Processes events for registered sockets and timers and calls whatever
  * handlers have been set up for these events.
  */
-void Application::RunEventLoop(void) const
+void Application::RunEventLoop(void)
 {
        Timer::Initialize();
 
@@ -254,7 +262,7 @@ mainloop:
                        goto mainloop;
 
                l_Restarting = true;
-               StartReloadProcess();
+               m_ReloadProcess = StartReloadProcess();
 
                goto mainloop;
        }
@@ -285,7 +293,7 @@ static void ReloadProcessCallback(const ProcessResult& pr)
        l_Restarting = false;
 }
 
-void Application::StartReloadProcess(void) const
+pid_t Application::StartReloadProcess(void)
 {
        Log(LogInformation, "base", "Got reload command: Starting new instance.");
 
@@ -305,6 +313,8 @@ void Application::StartReloadProcess(void) const
        Process::Ptr process = make_shared<Process>(Process::PrepareCommand(args));
        process->SetTimeout(300);
        process->Run(&ReloadProcessCallback);
+    
+       return process->GetHandle();
 }
 
 /**
@@ -619,8 +629,9 @@ int Application::Run(void)
  * if the PID file is already locked by another instance of the application.
  *
  * @param filename The name of the PID file.
+ * @param pid The PID to write; default is the current PID
  */
-void Application::UpdatePidFile(const String& filename)
+void Application::UpdatePidFile(const String& filename, pid_t pid)
 {
        ASSERT(!OwnsLock());
        ObjectLock olock(this);
@@ -663,7 +674,7 @@ void Application::UpdatePidFile(const String& filename)
        }
 #endif /* _WIN32 */
 
-       fprintf(m_PidFile, "%d\n", Utility::GetPid());
+       fprintf(m_PidFile, "%d\n", pid);
        fflush(m_PidFile);
 }
 
index 1c15f3ceadf34cf1d403b487e5f61c3bbd33fd75..28e589d96ef2f0ac79dc3fa2c6b43021520c1520 100644 (file)
@@ -23,6 +23,7 @@
 #include "base/i2-base.h"
 #include "base/application.th"
 #include "base/threadpool.h"
+#include "base/utility.h"
 
 namespace icinga
 {
@@ -67,7 +68,7 @@ public:
        static void SetDebugging(bool debug);
        static bool IsDebugging(void);
 
-       void UpdatePidFile(const String& filename);
+       void UpdatePidFile(const String& filename, pid_t pid = Utility::GetPid());
        void ClosePidFile(void);
        static pid_t ReadPidFile(const String& filename);
 
@@ -113,9 +114,9 @@ protected:
        virtual void OnConfigLoaded(void);
        virtual void Stop(void);
 
-       void RunEventLoop(void) const;
+       void RunEventLoop(void);
 
-       void StartReloadProcess(void) const;
+       pid_t StartReloadProcess(void);
 
        virtual void OnShutdown(void);
 
@@ -124,7 +125,10 @@ private:
 
        static bool m_ShuttingDown; /**< Whether the application is in the process of
                                  shutting down. */
-       static bool m_RequestRestart;
+       static bool m_RequestRestart; /**< A restart was requested through SIGHUP */
+       static pid_t m_ReloadProcess; /**< The PID of a subprocess doing a reload, 
+                                                                       only valid when l_Restarting==true */
+
        static int m_ArgC; /**< The number of command-line arguments. */
        static char **m_ArgV; /**< Command-line arguments. */
        FILE *m_PidFile; /**< The PID file */
index 904961734162e115e293ca708ef818ec37b7c140..548d3ad690d79aa0345b853427bbc4a729efda4b 100644 (file)
@@ -636,6 +636,12 @@ bool Process::DoEvents(void)
        return false;
 }
 
+Process::ProcessHandle Process::GetHandle(void) const
+{
+       return m_Process;
+}
+
+
 int Process::GetTID(void) const
 {
        return (reinterpret_cast<uintptr_t>(this) / sizeof(void *)) % IOTHREADS;
index d367bfa7a89161017a8beaaf132f0e83f2efea09..eb73e6c5c48fdbd266032595bfa67407762d1e99 100644 (file)
@@ -73,6 +73,8 @@ public:
 
        void Run(const boost::function<void (const ProcessResult&)>& callback = boost::function<void (const ProcessResult&)>());
 
+       ProcessHandle GetHandle(void) const;
+
        static Arguments PrepareCommand(const Value& command);
 
        static void StaticInitialize(void);