}
#endif /* _WIN32 */
-static bool Daemonize(const String& stderrFile)
+static bool Daemonize(void)
{
#ifndef _WIN32
pid_t pid = fork();
}
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)
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();
}
// 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();
}
/**
* 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;
}
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);