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) {
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"))
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;
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();
* 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();
goto mainloop;
l_Restarting = true;
- StartReloadProcess();
+ m_ReloadProcess = StartReloadProcess();
goto mainloop;
}
l_Restarting = false;
}
-void Application::StartReloadProcess(void) const
+pid_t Application::StartReloadProcess(void)
{
Log(LogInformation, "base", "Got reload command: Starting new instance.");
Process::Ptr process = make_shared<Process>(Process::PrepareCommand(args));
process->SetTimeout(300);
process->Run(&ReloadProcessCallback);
+
+ return process->GetHandle();
}
/**
* 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);
}
#endif /* _WIN32 */
- fprintf(m_PidFile, "%d\n", Utility::GetPid());
+ fprintf(m_PidFile, "%d\n", pid);
fflush(m_PidFile);
}
#include "base/i2-base.h"
#include "base/application.th"
#include "base/threadpool.h"
+#include "base/utility.h"
namespace icinga
{
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);
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);
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 */
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;
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);