Exemplo n.º 1
0
    def daemonize(self):
        """Creates the daemon.

        It will fork a child process and then exit parent. By performing a
        double fork, set the current process's user id, change the current
        working directory, set the current numeric umask, redirect standard
        streams and write the pid to a file.
        """
        def redirect_stream(system_stream, target_stream):
            """Redirect a system stream to a specified file.
            """
            if target_stream is None:
                target_f = os.open(os.devnull, os.O_RDWR)
            else:
                target_f = target_stream.fileno()
            os.dup2(target_f, system_stream.fileno())

        def fork_then_exit_parent(error_message):
            """Fork a child process, then exit the parent process.
            """
            try:
                pid = os.fork()
                if pid > 0:
                    os._exit(0)  # pylint: disable=W0212
            except OSError as err:
                msg = "{0}: [{1}] {2}".format(error_message, err.errno,
                                              err.strerror)
                self._report(msg, logging.CRITICAL)
                raise UtilDaemonError(msg)

        # Fork
        fork_then_exit_parent("Failed first fork.")

        try:
            os.setsid()
            os.chdir(self.chdir)
            os.umask(self.umask)
        except Exception as err:
            msg = "Unable to change directory ({0})".format(err)
            self._report(msg, logging.CRITICAL)
            raise UtilDaemonError(msg)

        # Double fork
        fork_then_exit_parent("Failed second fork.")

        # Redirect streams
        redirect_stream(sys.stdin, self.stdin)
        redirect_stream(sys.stdout, self.stdout)
        redirect_stream(sys.stderr, self.stderr)

        # write pidfile
        atexit.register(self.delete_pidfile)
        pid = str(os.getpid())
        try:
            with open(self.pidfile, "w") as f:
                f.write("{0}\n".format(pid))
        except IOError as err:
            msg = "Unable to write pidfile: {0}".format(err.strerror)
            self._report(msg, logging.CRITICAL)
            raise UtilDaemonError(msg)
Exemplo n.º 2
0
    def start(self, detach_process=True):
        """Starts the daemon.

        It will start the daemon if detach_process is True.
        """
        if detach_process:
            # Check for a pidfile presence
            try:
                with open(self.pidfile, "rb") as f:
                    self.pid = int(f.read().strip())
            except IOError:
                self.pid = None
            except SystemExit:
                self.pid = None
            except ValueError:
                self.pid = None

            if self.pid:
                # Daemon already runs
                msg = ("pidfile {0} already exists. The daemon is already "
                       "running?".format(self.pidfile))
                self._report(msg, logging.CRITICAL)
                raise UtilDaemonError(msg)

            # Start the daemon
            self.daemonize()

        # Run automatic failover
        return self.run()
Exemplo n.º 3
0
    def stop(self):
        """Stops the daemon.

        It will stop the daemon by sending a signal.SIGTERM to the process.
        """
        # Get the pid from the pidfile
        try:
            with open(self.pidfile, "rb") as f:
                self.pid = int(f.read().strip())
        except IOError:
            self._report("pidfile {0} does not exist.".format(self.pidfile),
                         logging.ERROR)
            return False
        except ValueError:
            self._report("Invalid pid in pidfile {0}.".format(self.pidfile),
                         logging.ERROR)
            return False

        # Kill the daemon process
        try:
            while 1:
                os.kill(self.pid, signal.SIGTERM)
                time.sleep(0.1)
        except OSError as err:
            strerror = err.strerror
            if err.errno == 3:  # No such process
                if os.path.exists(self.pidfile):
                    self.delete_pidfile()
            else:
                msg = "Unable to delete pidfile: {0}".format(strerror)
                self._report(msg, logging.ERROR)
                raise UtilDaemonError(msg)

        return True
Exemplo n.º 4
0
 def delete_pidfile(self):
     """Deletes pidfile.
     """
     try:
         os.remove(self.pidfile)
     except (OSError, IOError) as err:
         msg = "Unable to delete pidfile: {0}".format(err.strerror)
         self._report(msg, logging.ERROR)
         raise UtilDaemonError(msg)
Exemplo n.º 5
0
 def fork_then_exit_parent(error_message):
     """Fork a child process, then exit the parent process.
     """
     try:
         pid = os.fork()
         if pid > 0:
             os._exit(0)  # pylint: disable=W0212
     except OSError as err:
         msg = "{0}: [{1}] {2}".format(error_message, err.errno,
                                       err.strerror)
         self._report(msg, logging.CRITICAL)
         raise UtilDaemonError(msg)