Browse Source

Pulled in the daemon class from the earlier stdd project and made some corrections to it.

Helmut Pozimski 10 years ago
parent
commit
8cdcfa10a0
1 changed files with 123 additions and 0 deletions
  1. 123 0
      jwmudlib/daemon.py

+ 123 - 0
jwmudlib/daemon.py

@@ -0,0 +1,123 @@
+# This file is part of jwmud, written by Helmut Pozimski in 2014.
+#
+#       jwmud is free software: you can redistribute it and/or modify
+#       it under the terms of the GNU General Public License as published by
+#       the Free Software Foundation, version 2 of the License.
+#
+#       jwmud is distributed in the hope that it will be useful,
+#       but WITHOUT ANY WARRANTY; without even the implied warranty of
+#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#       GNU General Public License for more details.
+#
+#       You should have received a copy of the GNU General Public License
+#       along with jwmud.  If not, see <http://www.gnu.org/licenses/>.
+
+# -*- coding: utf8 -*-
+
+import os
+import sys
+
+
+class Daemon(object):
+    """ Tries to implement a well behaving unix daemon in a generic way,
+    so the code could be used in different projects.
+
+    """
+
+    def __init__(self, pfile_path, pfile_name):
+        """ Initializes the object. """
+        self.__pfile_path = pfile_path
+        self.__pfile_name = pfile_name
+        self.__daemon = False
+        self.__pid = 0
+        self.__pidfile = ""
+
+    def Daemonize(self):
+        """ Turns the calling process into a daemon running on it's own """
+
+        try:
+            # Fork for the first time
+            self.__pid = os.fork()
+        except OSError:
+            sys.exit(os.EX_OSERR)
+        else:
+            if self.__pid > 0:
+                sys.exit(os.EX_OK)
+        # Become session and group leader
+        # noinspection PyArgumentList
+        os.setsid()
+        try:
+            #Fork for the second time
+            self.__pid = os.fork()
+        except OSError:
+            sys.exit(os.EX_OSERR)
+        else:
+            if self.__pid > 0:
+                sys.exit(os.EX_OK)
+        # Change cwd to / to avoid interfering with other mounted file systems
+        os.chdir("/")
+        # Reset the umask
+        os.umask(0)
+
+        # Close possibly open file descriptors
+        os.close(0)
+        os.close(1)
+        os.close(2)
+
+        # And redirect them to /dev/null
+        os.open("/dev/null", 0)
+        os.open("/dev/null", 1)
+        os.open("/dev/null", 2)
+
+        self.__daemon = True
+
+    def DropPriv(self, uid, gid):
+        """ If the daemon is running as root user, drop privileges and continue
+        running as the defined unprivileged user """
+        if os.getuid() == 0:
+            os.setgid(gid)
+            os.setuid(uid)
+
+    def SetName(self, name, cmdline):
+        """ Sets the name of the process shown visible in ps and top,
+        this allows to make your daemon look more like a standalone
+        program instead of a python script.
+
+        """
+        try:
+            # First check if prctl is available, otherwise this
+            # function does nothing
+            # noinspection PyUnresolvedReferences
+            import prctl
+        except ImportError:
+            return False
+        else:
+            prctl.set_name(name)
+            prctl.set_proctitle(cmdline)
+            return True
+
+    def Start(self):
+        """ Performs the operations needed to "start" the daemon """
+        if self.__daemon is True:
+            if os.access(self.__pfile_path, os.F_OK & os.W_OK):
+                self.__pidfile = open(os.path.join(self.__pfile_path,
+                                                   self.__pfile_name), "w")
+                self.__pidfile.write(str(os.getpid()) + "\n")
+                self.__pidfile.close()
+                return True
+            else:
+                return False
+        else:
+            return False
+
+    def Stop(self):
+        """ Performs the operations needed to stop the daemon """
+        if self.__daemon is True:
+            try:
+                os.remove(os.path.join(self.__pfile_path, self.__pfile_name))
+            except OSError:
+                return False
+            else:
+                return True
+        else:
+            return True