Ver Fonte

Ignore permission denied errors when removing pidfile.

Ask Solem há 15 anos atrás
pai
commit
35e3e69cf5
1 ficheiros alterados com 82 adições e 11 exclusões
  1. 82 11
      celery/platform.py

+ 82 - 11
celery/platform.py

@@ -18,6 +18,29 @@ except ImportError:
 from celery.utils import noop
 from celery.utils import noop
 
 
 
 
+def maybe_remove_file(path, ignore_perm_denied=False):
+    """Try to unlink file, but don't care if it doesn't exist.
+
+    :param path: The path of the file to remove.
+    :keyword ignore_perm_denied: Ignore permission denied errors.
+
+    """
+    try:
+        os.unlink(filename)
+    except OSError, exc:
+        if exc.errno == errno.ENOENT:
+            return
+        if exc.errno == errno.EACCES and ignore_perm_denied:
+            return
+        raise
+
+
+def remove_pidlock(pidfile):
+    """Remove pidfile created by :class:`daemon.pidlockfile.PIDLockFile`."""
+    maybe_remove_file(pidfile)
+    maybe_remove_file("%s.lock" % pidfile)
+
+
 def acquire_pidlock(pidfile):
 def acquire_pidlock(pidfile):
     """Get the :class:`daemon.pidlockfile.PIDLockFile` handler for
     """Get the :class:`daemon.pidlockfile.PIDLockFile` handler for
     ``pidfile``.
     ``pidfile``.
@@ -29,9 +52,18 @@ def acquire_pidlock(pidfile):
     running in the background somewhere.
     running in the background somewhere.
 
 
     """
     """
-    from daemon.pidlockfile import PIDLockFile
+    from daemon.pidlockfile import PIDLockFile as _PIDLockFile
+    from lockfile import LinkFileLock
     import errno
     import errno
-    pidlock = PIDLockFile(pidfile)
+
+    class SafeRemovePIDLockFile(_PIDLockFile):
+
+        def release(self):
+            if self.i_am_locking():
+                maybe_remove_file(self.path, ignore_perm_denied=True)
+            LinkFileLock.release(self)
+
+    pidlock = SafeRemovePIDLockFile(pidfile)
     if not pidlock.is_locked():
     if not pidlock.is_locked():
         return pidlock
         return pidlock
     pid = pidlock.read_pid()
     pid = pidlock.read_pid()
@@ -40,12 +72,12 @@ def acquire_pidlock(pidfile):
     except os.error, exc:
     except os.error, exc:
         if exc.errno == errno.ESRCH:
         if exc.errno == errno.ESRCH:
             sys.stderr.write("Stale pidfile exists. Removing it.\n")
             sys.stderr.write("Stale pidfile exists. Removing it.\n")
-            os.unlink(pidfile)
-            return PIDLockFile(pidfile)
+            remove_pidlock(pidfile)
+            return SafeRemovePIDLockFile(pidfile)
     except TypeError, exc:
     except TypeError, exc:
         sys.stderr.write("Broken pidfile found. Removing it.\n")
         sys.stderr.write("Broken pidfile found. Removing it.\n")
-        os.unlink(pidfile)
-        return PIDLockFile(pidfile)
+        remove_pidlock(pidfile)
+        return SafeRemovePIDLockFile(pidfile)
     else:
     else:
         raise SystemExit(
         raise SystemExit(
                 "ERROR: Pidfile (%s) already exists.\n"
                 "ERROR: Pidfile (%s) already exists.\n"
@@ -74,9 +106,6 @@ def create_daemon_context(logfile=None, pidfile=None, **options):
 
 
     options["pidfile"] = pidfile and acquire_pidlock(pidfile)
     options["pidfile"] = pidfile and acquire_pidlock(pidfile)
 
 
-    #options["uid"] = os.getuid()
-    #options["gid"] = os.getgid()
-
     defaults = {"umask": lambda: 0,
     defaults = {"umask": lambda: 0,
                 "chroot_directory": lambda: None,
                 "chroot_directory": lambda: None,
                 "working_directory": lambda: os.getcwd()}
                 "working_directory": lambda: os.getcwd()}
@@ -91,20 +120,33 @@ def create_daemon_context(logfile=None, pidfile=None, **options):
 
 
 
 
 def reset_signal(signal_name):
 def reset_signal(signal_name):
+    """Reset signal to the default signal handler.
+
+    Does nothing if the platform doesn't support signals,
+    or the specified signal in particular.
+
+    """
     if hasattr(signal, signal_name):
     if hasattr(signal, signal_name):
         signal.signal(getattr(signal, signal_name), signal.SIG_DFL)
         signal.signal(getattr(signal, signal_name), signal.SIG_DFL)
 
 
 
 
 def install_signal_handler(signal_name, handler):
 def install_signal_handler(signal_name, handler):
-    """Install a SIGHUP handler."""
+    """Install a handler.
+
+    Does nothing if the current platform doesn't support signals,
+    or the specified signal in particular.
+
+    """
     if not hasattr(signal, signal_name):
     if not hasattr(signal, signal_name):
-        return # Platform doesn't support signal.
+        return
 
 
     signum = getattr(signal, signal_name)
     signum = getattr(signal, signal_name)
     signal.signal(signum, handler)
     signal.signal(signum, handler)
 
 
 
 
 def set_process_title(progname, info=None):
 def set_process_title(progname, info=None):
+    """Set the ps name for the currently running process
+    if :mod`setproctitle` is installed."""
     if _setproctitle:
     if _setproctitle:
         proctitle = "[%s]" % progname
         proctitle = "[%s]" % progname
         proctitle = info and "%s %s" % (proctitle, info) or proctitle
         proctitle = info and "%s %s" % (proctitle, info) or proctitle
@@ -112,12 +154,23 @@ def set_process_title(progname, info=None):
 
 
 
 
 def set_mp_process_title(progname, info=None):
 def set_mp_process_title(progname, info=None):
+    """Set the ps name using the multiprocessing process name.
+
+    Only works if :mod:`setproctitle` is installed.
+
+    """
     from multiprocessing.process import current_process
     from multiprocessing.process import current_process
     return set_process_title("%s.%s" % (progname, current_process().name),
     return set_process_title("%s.%s" % (progname, current_process().name),
                              info=info)
                              info=info)
 
 
 
 
 def parse_uid(uid):
 def parse_uid(uid):
+    """Parse user uid.
+
+    uid can be an integer (uid) or a string (username), if it's a username
+    the uid is taken from the system password system.
+
+    """
     try:
     try:
         return int(uid)
         return int(uid)
     except ValueError:
     except ValueError:
@@ -125,6 +178,12 @@ def parse_uid(uid):
 
 
 
 
 def parse_gid(gid):
 def parse_gid(gid):
+    """Parse group gid.
+
+    gid can be an integer (gid) or a string (group name), if it's a name
+    the gid is taken from the system password system.
+
+    """
     try:
     try:
         return int(gid)
         return int(gid)
     except ValueError:
     except ValueError:
@@ -132,18 +191,30 @@ def parse_gid(gid):
 
 
 
 
 def setegid(gid):
 def setegid(gid):
+    """Set effective group id."""
     gid = parse_uid(gid)
     gid = parse_uid(gid)
     if gid != os.getgid():
     if gid != os.getgid():
         os.setegid(gid)
         os.setegid(gid)
 
 
 
 
 def seteuid(uid):
 def seteuid(uid):
+    """Set effective user id."""
     uid = parse_uid(uid)
     uid = parse_uid(uid)
     if uid != os.getuid():
     if uid != os.getuid():
         os.seteuid(uid)
         os.seteuid(uid)
 
 
 
 
 def set_effective_user(uid=None, gid=None):
 def set_effective_user(uid=None, gid=None):
+    """Change privileges to a new user/group.
+
+    If uid and gid is set the effective user/group is set.
+
+    If only uid is set, the effective user is set, and the group is set
+    to the users primary group.
+
+    If only gid is set, the effective group is set.
+
+    """
     # gid/uid can be int or username/groupname.
     # gid/uid can be int or username/groupname.
     uid = uid and parse_uid(uid)
     uid = uid and parse_uid(uid)
     gid = gid and parse_gid(gid)
     gid = gid and parse_gid(gid)