mirror of https://github.com/Icinga/icinga2.git
commit
1e57861486
|
@ -161,7 +161,7 @@ static void SigHupHandler(int)
|
||||||
}
|
}
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
static bool Daemonize(const String& stderrFile)
|
static bool Daemonize(void)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
|
@ -169,9 +169,39 @@ static bool Daemonize(const String& stderrFile)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid)
|
if (pid) {
|
||||||
exit(0);
|
// systemd requires that the pidfile of the daemon is written before the forking
|
||||||
|
// process terminates. So wait till either the forked daemon has written a pidfile or died.
|
||||||
|
|
||||||
|
int status;
|
||||||
|
int ret;
|
||||||
|
pid_t readpid;
|
||||||
|
do {
|
||||||
|
Utility::Sleep(0.1);
|
||||||
|
|
||||||
|
readpid = Application::ReadPidFile(Application::GetPidPath());
|
||||||
|
ret = waitpid(pid, &status, WNOHANG);
|
||||||
|
} while (readpid != pid && ret == 0);
|
||||||
|
|
||||||
|
if (ret == pid) {
|
||||||
|
Log(LogCritical, "icinga-app", "The daemon could not be started. See logfile for details.");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else if (ret == -1) {
|
||||||
|
BOOST_THROW_EXCEPTION(posix_error()
|
||||||
|
<< boost::errinfo_api_function("waitpid")
|
||||||
|
<< boost::errinfo_errno(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool SetDaemonIO(const String& stderrFile)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
int fdnull = open("/dev/null", O_RDWR);
|
int fdnull = open("/dev/null", O_RDWR);
|
||||||
if (fdnull >= 0) {
|
if (fdnull >= 0) {
|
||||||
if (fdnull != 0)
|
if (fdnull != 0)
|
||||||
|
@ -484,12 +514,16 @@ int Main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_AppParams.count("daemonize")) {
|
if (g_AppParams.count("daemonize")) {
|
||||||
String errorLog;
|
if (!g_AppParams.count("reload-internal")) {
|
||||||
|
// no additional fork neccessary on reload
|
||||||
|
Daemonize();
|
||||||
|
}
|
||||||
|
|
||||||
|
String errorLog;
|
||||||
if (g_AppParams.count("errorlog"))
|
if (g_AppParams.count("errorlog"))
|
||||||
errorLog = g_AppParams["errorlog"].as<std::string>();
|
errorLog = g_AppParams["errorlog"].as<std::string>();
|
||||||
|
|
||||||
Daemonize(errorLog);
|
SetDaemonIO(errorLog);
|
||||||
Logger::DisableConsoleLog();
|
Logger::DisableConsoleLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ REGISTER_TYPE(Application);
|
||||||
Application *Application::m_Instance = NULL;
|
Application *Application::m_Instance = NULL;
|
||||||
bool Application::m_ShuttingDown = false;
|
bool Application::m_ShuttingDown = false;
|
||||||
bool Application::m_RequestRestart = false;
|
bool Application::m_RequestRestart = false;
|
||||||
|
pid_t Application::m_ReloadProcess = 0;
|
||||||
static bool l_Restarting = false;
|
static bool l_Restarting = false;
|
||||||
bool Application::m_Debugging = false;
|
bool Application::m_Debugging = false;
|
||||||
int Application::m_ArgC;
|
int Application::m_ArgC;
|
||||||
|
@ -91,7 +92,15 @@ void Application::Stop(void)
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
ClosePidFile();
|
// 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(false);
|
||||||
|
} else
|
||||||
|
ClosePidFile(true);
|
||||||
|
|
||||||
DynamicObject::Stop();
|
DynamicObject::Stop();
|
||||||
}
|
}
|
||||||
|
@ -218,7 +227,7 @@ void Application::SetArgV(char **argv)
|
||||||
* Processes events for registered sockets and timers and calls whatever
|
* Processes events for registered sockets and timers and calls whatever
|
||||||
* handlers have been set up for these events.
|
* handlers have been set up for these events.
|
||||||
*/
|
*/
|
||||||
void Application::RunEventLoop(void) const
|
void Application::RunEventLoop(void)
|
||||||
{
|
{
|
||||||
Timer::Initialize();
|
Timer::Initialize();
|
||||||
|
|
||||||
|
@ -254,7 +263,7 @@ mainloop:
|
||||||
goto mainloop;
|
goto mainloop;
|
||||||
|
|
||||||
l_Restarting = true;
|
l_Restarting = true;
|
||||||
StartReloadProcess();
|
m_ReloadProcess = StartReloadProcess();
|
||||||
|
|
||||||
goto mainloop;
|
goto mainloop;
|
||||||
}
|
}
|
||||||
|
@ -285,7 +294,7 @@ static void ReloadProcessCallback(const ProcessResult& pr)
|
||||||
l_Restarting = false;
|
l_Restarting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::StartReloadProcess(void) const
|
pid_t Application::StartReloadProcess(void)
|
||||||
{
|
{
|
||||||
Log(LogInformation, "base", "Got reload command: Starting new instance.");
|
Log(LogInformation, "base", "Got reload command: Starting new instance.");
|
||||||
|
|
||||||
|
@ -305,6 +314,8 @@ void Application::StartReloadProcess(void) const
|
||||||
Process::Ptr process = make_shared<Process>(Process::PrepareCommand(args));
|
Process::Ptr process = make_shared<Process>(Process::PrepareCommand(args));
|
||||||
process->SetTimeout(300);
|
process->SetTimeout(300);
|
||||||
process->Run(&ReloadProcessCallback);
|
process->Run(&ReloadProcessCallback);
|
||||||
|
|
||||||
|
return process->GetPID();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -619,8 +630,9 @@ int Application::Run(void)
|
||||||
* if the PID file is already locked by another instance of the application.
|
* if the PID file is already locked by another instance of the application.
|
||||||
*
|
*
|
||||||
* @param filename The name of the PID file.
|
* @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());
|
ASSERT(!OwnsLock());
|
||||||
ObjectLock olock(this);
|
ObjectLock olock(this);
|
||||||
|
@ -663,20 +675,27 @@ void Application::UpdatePidFile(const String& filename)
|
||||||
}
|
}
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
fprintf(m_PidFile, "%d\n", Utility::GetPid());
|
fprintf(m_PidFile, "%d\n", pid);
|
||||||
fflush(m_PidFile);
|
fflush(m_PidFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the PID file. Does nothing if the PID file is not currently open.
|
* Closes the PID file. Does nothing if the PID file is not currently open.
|
||||||
*/
|
*/
|
||||||
void Application::ClosePidFile(void)
|
void Application::ClosePidFile(bool unlink)
|
||||||
{
|
{
|
||||||
ASSERT(!OwnsLock());
|
ASSERT(!OwnsLock());
|
||||||
ObjectLock olock(this);
|
ObjectLock olock(this);
|
||||||
|
|
||||||
if (m_PidFile != NULL)
|
if (m_PidFile != NULL)
|
||||||
|
{
|
||||||
|
if (unlink) {
|
||||||
|
String pidpath = GetPidPath();
|
||||||
|
::unlink(pidpath.CStr());
|
||||||
|
}
|
||||||
|
|
||||||
fclose(m_PidFile);
|
fclose(m_PidFile);
|
||||||
|
}
|
||||||
|
|
||||||
m_PidFile = NULL;
|
m_PidFile = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "base/i2-base.h"
|
#include "base/i2-base.h"
|
||||||
#include "base/application.th"
|
#include "base/application.th"
|
||||||
#include "base/threadpool.h"
|
#include "base/threadpool.h"
|
||||||
|
#include "base/utility.h"
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
@ -67,8 +68,8 @@ public:
|
||||||
static void SetDebugging(bool debug);
|
static void SetDebugging(bool debug);
|
||||||
static bool IsDebugging(void);
|
static bool IsDebugging(void);
|
||||||
|
|
||||||
void UpdatePidFile(const String& filename);
|
void UpdatePidFile(const String& filename, pid_t pid = Utility::GetPid());
|
||||||
void ClosePidFile(void);
|
void ClosePidFile(bool unlink);
|
||||||
static pid_t ReadPidFile(const String& filename);
|
static pid_t ReadPidFile(const String& filename);
|
||||||
|
|
||||||
static String GetExePath(const String& argv0);
|
static String GetExePath(const String& argv0);
|
||||||
|
@ -113,9 +114,9 @@ protected:
|
||||||
virtual void OnConfigLoaded(void);
|
virtual void OnConfigLoaded(void);
|
||||||
virtual void Stop(void);
|
virtual void Stop(void);
|
||||||
|
|
||||||
void RunEventLoop(void) const;
|
void RunEventLoop(void);
|
||||||
|
|
||||||
void StartReloadProcess(void) const;
|
pid_t StartReloadProcess(void);
|
||||||
|
|
||||||
virtual void OnShutdown(void);
|
virtual void OnShutdown(void);
|
||||||
|
|
||||||
|
@ -124,7 +125,10 @@ private:
|
||||||
|
|
||||||
static bool m_ShuttingDown; /**< Whether the application is in the process of
|
static bool m_ShuttingDown; /**< Whether the application is in the process of
|
||||||
shutting down. */
|
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 int m_ArgC; /**< The number of command-line arguments. */
|
||||||
static char **m_ArgV; /**< Command-line arguments. */
|
static char **m_ArgV; /**< Command-line arguments. */
|
||||||
FILE *m_PidFile; /**< The PID file */
|
FILE *m_PidFile; /**< The PID file */
|
||||||
|
|
|
@ -410,9 +410,10 @@ void Process::Run(const boost::function<void(const ProcessResult&)>& callback)
|
||||||
|
|
||||||
m_Process = pi.hProcess;
|
m_Process = pi.hProcess;
|
||||||
m_FD = outReadPipe;
|
m_FD = outReadPipe;
|
||||||
|
m_PID = pi.dwProcessId;
|
||||||
|
|
||||||
Log(LogInformation, "base", "Running command '" + m_Arguments +
|
Log(LogInformation, "base", "Running command '" + m_Arguments +
|
||||||
"': PID " + Convert::ToString(pi.dwProcessId));
|
"': PID " + Convert::ToString(m_PID));
|
||||||
|
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
int fds[2];
|
int fds[2];
|
||||||
|
@ -514,8 +515,10 @@ void Process::Run(const boost::function<void(const ProcessResult&)>& callback)
|
||||||
|
|
||||||
// parent process
|
// parent process
|
||||||
|
|
||||||
|
m_PID = m_Process;
|
||||||
|
|
||||||
Log(LogInformation, "base", "Running command '" + boost::algorithm::join(m_Arguments, " ") +
|
Log(LogInformation, "base", "Running command '" + boost::algorithm::join(m_Arguments, " ") +
|
||||||
"': PID " + Convert::ToString(m_Process));
|
"': PID " + Convert::ToString(m_PID));
|
||||||
|
|
||||||
m_Arguments.clear();
|
m_Arguments.clear();
|
||||||
|
|
||||||
|
@ -636,6 +639,12 @@ bool Process::DoEvents(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid_t Process::GetPID(void) const
|
||||||
|
{
|
||||||
|
return m_PID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Process::GetTID(void) const
|
int Process::GetTID(void) const
|
||||||
{
|
{
|
||||||
return (reinterpret_cast<uintptr_t>(this) / sizeof(void *)) % IOTHREADS;
|
return (reinterpret_cast<uintptr_t>(this) / sizeof(void *)) % IOTHREADS;
|
||||||
|
|
|
@ -73,6 +73,8 @@ public:
|
||||||
|
|
||||||
void Run(const boost::function<void (const ProcessResult&)>& callback = boost::function<void (const ProcessResult&)>());
|
void Run(const boost::function<void (const ProcessResult&)>& callback = boost::function<void (const ProcessResult&)>());
|
||||||
|
|
||||||
|
pid_t GetPID(void) const;
|
||||||
|
|
||||||
static Arguments PrepareCommand(const Value& command);
|
static Arguments PrepareCommand(const Value& command);
|
||||||
|
|
||||||
static void StaticInitialize(void);
|
static void StaticInitialize(void);
|
||||||
|
@ -85,6 +87,7 @@ private:
|
||||||
double m_Timeout;
|
double m_Timeout;
|
||||||
|
|
||||||
ProcessHandle m_Process;
|
ProcessHandle m_Process;
|
||||||
|
pid_t m_PID;
|
||||||
ConsoleHandle m_FD;
|
ConsoleHandle m_FD;
|
||||||
|
|
||||||
std::ostringstream m_OutputStream;
|
std::ostringstream m_OutputStream;
|
||||||
|
|
Loading…
Reference in New Issue