Unlink the pidfile when we really shutdown (not reload).

Refs #6118
This commit is contained in:
Gerd von Egidy 2014-05-18 16:23:16 +02:00 committed by Gunnar Beutner
parent e93a22b440
commit e0d4b9fb80
3 changed files with 51 additions and 12 deletions

View File

@ -161,7 +161,7 @@ static void SigHupHandler(int)
}
#endif /* _WIN32 */
static bool Daemonize(const String& stderrFile)
static bool Daemonize(void)
{
#ifndef _WIN32
pid_t pid = fork();
@ -170,11 +170,38 @@ static bool Daemonize(const String& stderrFile)
}
if (pid) {
// TODO: do a real wait till the pidfile is written by the daemon
Utility::Sleep(5);
// 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);
if (fdnull >= 0) {
if (fdnull != 0)
@ -486,13 +513,17 @@ int Main(void)
Log(LogInformation, "icinga-app", "Previous instance has ended, taking over now.");
}
if (g_AppParams.count("daemonize") && !g_AppParams.count("reload-internal")) {
String errorLog;
if (g_AppParams.count("daemonize")) {
if (!g_AppParams.count("reload-internal")) {
// no additional fork neccessary on reload
Daemonize();
}
String errorLog;
if (g_AppParams.count("errorlog"))
errorLog = g_AppParams["errorlog"].as<std::string>();
Daemonize(errorLog);
SetDaemonIO(errorLog);
Logger::DisableConsoleLog();
}

View File

@ -96,10 +96,11 @@ void Application::Stop(void)
// 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();
if (l_Restarting) {
UpdatePidFile(GetPidPath(), m_ReloadProcess);
ClosePidFile(false);
} else
ClosePidFile(true);
DynamicObject::Stop();
}
@ -681,13 +682,20 @@ void Application::UpdatePidFile(const String& filename, pid_t pid)
/**
* 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());
ObjectLock olock(this);
if (m_PidFile != NULL)
{
if (unlink) {
String pidpath = GetPidPath();
::unlink(pidpath.CStr());
}
fclose(m_PidFile);
}
m_PidFile = NULL;
}

View File

@ -69,7 +69,7 @@ public:
static bool IsDebugging(void);
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 String GetExePath(const String& argv0);