]> granicus.if.org Git - icinga2/commitdiff
Unlink the pidfile when we really shutdown (not reload).
authorGerd von Egidy <gerd@egidy.de>
Sun, 18 May 2014 14:23:16 +0000 (16:23 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Sun, 18 May 2014 16:44:54 +0000 (18:44 +0200)
Refs #6118

icinga-app/icinga.cpp
lib/base/application.cpp
lib/base/application.h

index 05d359d773032f8f895b98d35c7b5ef6a948a2be..3b023fad8c696ec1aa78b3a9ff3fd39bb02f0549 100644 (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();
        }
 
index 4dca020280b2fa6cd6cd5b23f504ad6886fcc192..9de7f7d4dc8f8fb12cf5a65870f15d5324194d72 100644 (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;
 }
index 28e589d96ef2f0ac79dc3fa2c6b43021520c1520..490937d074c591d8ec79b63f420df804858b6a10 100644 (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);