Browse Source

Try not using python-daemon to detach

Ask Solem 15 years ago
parent
commit
6194a90246
1 changed files with 58 additions and 5 deletions
  1. 58 5
      celery/platform.py

+ 58 - 5
celery/platform.py

@@ -2,8 +2,9 @@ import os
 import sys
 import pwd
 import grp
-import signal
 import errno
+import atexit
+import signal
 try:
     from setproctitle import setproctitle as _setproctitle
 except ImportError:
@@ -18,6 +19,11 @@ except ImportError:
 
 from celery.utils import noop
 
+DAEMON_UMASK = 0
+DAEMON_WORKDIR = "/"
+DAEMON_MAXFD = 1024
+DAEMON_REDIRECT_TO = getattr(os, "devnull", "/dev/null")
+
 
 def create_pidlock(pidfile):
     """Create a PIDFile to be used with python-daemon.
@@ -83,14 +89,61 @@ def create_pidlock(pidfile):
     return pidlock
 
 
+class DaemonContext(object):
+    _is_open = False
+
+    def __init__(self, pidfile=None, chroot_directory=None, 
+            working_directory=DAEMON_WORKDIR, umask=DAEMON_UMASK, **kwargs):
+        self.pidfile = pidfile
+        self.chroot_directory = chroot_directory
+        self.working_directory = working_directory
+        self.umask = umask
+
+    def detach(self):
+        if os.fork() == 0: # first child
+            os.setsid() # create new session.
+            if os.fork() > 0: # second child
+                os._exit(0)
+        else:
+            os._exit(0)
+
+    def open(self):
+        from daemon import daemon
+        if self._is_open:
+            return
+
+        self.detach()
+
+        if self.pidfile is not None:
+                self.pidfile.__enter__()
+
+        if self.chroot_directory is not None:
+            daemon.change_root_directory(self.chroot_directory)
+        os.chdir(self.working_directory)
+        os.umask(self.umask)
+
+        daemon.close_all_open_files()
+
+        os.open(DAEMON_REDIRECT_TO, os.O_RDWR)
+        os.dup2(0, 1)
+        os.dup2(0, 2)
+
+        self._is_open = True
+        atexit.register(self.close)
+
+    def close(self):
+        if not self._is_open:
+            return
+        if self.pidfile is not None:
+            self.pidfile.__exit__()
+        self._is_open = False
+
+
 def create_daemon_context(logfile=None, pidfile=None, **options):
     if not CAN_DETACH:
         raise RuntimeError(
                 "This operating system doesn't support detach.")
 
-    import daemon
-    daemon.change_process_owner = noop # We handle our own user change.
-
     # set SIGCLD back to the default SIG_DFL (before python-daemon overrode
     # it) lets the parent wait() for the terminated child process and stops
     # the 'OSError: [Errno 10] No child processes' problem.
@@ -111,7 +164,7 @@ def create_daemon_context(logfile=None, pidfile=None, **options):
         if opt_name not in options or options[opt_name] is None:
             options[opt_name] = opt_default_gen()
 
-    context = daemon.DaemonContext(**options)
+    context = DaemonContext(**options)
 
     return context, context.close