platform.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import os
  2. import sys
  3. import signal
  4. CAN_DETACH = True
  5. try:
  6. import resource
  7. except ImportError:
  8. CAN_DETACH = False
  9. def acquire_pidlock(pidfile):
  10. """Get the :class:`daemon.pidlockfile.PIDLockFile` handler for
  11. ``pidfile``.
  12. If the ``pidfile`` already exists, but the process is not running the
  13. ``pidfile`` will be removed, a ``"stale pidfile"`` message is emitted
  14. and execution continues as normally. However, if the process is still
  15. running the program will exit complaning that the program is already
  16. running in the background somewhere.
  17. """
  18. from daemon.pidlockfile import PIDLockFile
  19. import errno
  20. pidlock = PIDLockFile(pidfile)
  21. if not pidlock.is_locked():
  22. return pidlock
  23. pid = pidlock.read_pid()
  24. try:
  25. os.kill(pid, 0)
  26. except os.error, exc:
  27. if exc.errno == errno.ESRCH:
  28. sys.stderr.write("Stale pidfile exists. Removing it.\n")
  29. os.unlink(pidfile)
  30. return PIDLockFile(pidfile)
  31. except TypeError, exc:
  32. sys.stderr.write("Broken pidfile found. Removing it.\n")
  33. os.unlink(pidfile)
  34. return PIDLockFile(pidfile)
  35. else:
  36. raise SystemExit(
  37. "ERROR: Pidfile (%s) already exists.\n"
  38. "Seems celeryd is already running? (PID: %d)" % (
  39. pidfile, pid))
  40. return pidlock
  41. def create_daemon_context(logfile=None, pidfile=None, **options):
  42. if not CAN_DETACH:
  43. raise RuntimeError(
  44. "This operating system doesn't support detach.")
  45. from daemon import DaemonContext
  46. # Since without stderr any errors will be silently suppressed,
  47. # we need to know that we have access to the logfile
  48. if logfile:
  49. open(logfile, "a").close()
  50. options["pidlock"] = pidfile and acquire_pidlock(pidfile)
  51. defaults = {"uid": lambda: os.geteuid(),
  52. "gid": lambda: os.getegid(),
  53. "umask": lambda: 0,
  54. "chroot_directory": lambda: None,
  55. "working_directory": lambda: os.getcwd()}
  56. for opt_name, opt_default_gen in defaults.items():
  57. if opt_name not in options:
  58. options[opt_name] = opt_default_gen()
  59. return DaemonContext(chroot_directory=chroot,
  60. working_directory=working_directory,
  61. umask=umask,
  62. pidfile=pidlock,
  63. uid=uid,
  64. gid=gid)
  65. def reset_signal(signal_name):
  66. if hasattr(signal, signal_name):
  67. signal.signal(getattr(signal, signal_name), signal.SIG_DFL)
  68. def install_signal_handler(signal_name, handler):
  69. """Install a SIGHUP handler."""
  70. if not hasattr(signal, signal):
  71. return # Platform doesn't support signal.
  72. signum = getattr(signal, signal_name)
  73. signal.signal(signum, handler)