diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 666ae0c0c..05d359d77 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -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")) diff --git a/lib/base/application.cpp b/lib/base/application.cpp index 4b8672958..4dca02028 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -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::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); } diff --git a/lib/base/application.h b/lib/base/application.h index 1c15f3cea..28e589d96 100644 --- a/lib/base/application.h +++ b/lib/base/application.h @@ -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 */ diff --git a/lib/base/process.cpp b/lib/base/process.cpp index 904961734..548d3ad69 100644 --- a/lib/base/process.cpp +++ b/lib/base/process.cpp @@ -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(this) / sizeof(void *)) % IOTHREADS; diff --git a/lib/base/process.h b/lib/base/process.h index d367bfa7a..eb73e6c5c 100644 --- a/lib/base/process.h +++ b/lib/base/process.h @@ -73,6 +73,8 @@ public: void Run(const boost::function& callback = boost::function()); + ProcessHandle GetHandle(void) const; + static Arguments PrepareCommand(const Value& command); static void StaticInitialize(void);