platform.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import os
  2. import sys
  3. import errno
  4. import resource
  5. __all__ = ["PIDFile", "remove_pidfile", "daemonize"]
  6. # File mode creation mask of the daemon.
  7. # No point in changing this, as we don't really create any files.
  8. DAEMON_UMASK = 0
  9. # Default working directory for the daemon.
  10. DAEMON_WORKDIR = "/"
  11. # Default maximum for the number of available file descriptors.
  12. DAEMON_MAXFD = 1024
  13. # The standard I/O file descriptors are redirected to /dev/null by default.
  14. if (hasattr(os, "devnull")):
  15. REDIRECT_TO = os.devnull
  16. else:
  17. REDIRECT_TO = "/dev/null"
  18. class PIDFile(object):
  19. def __init__(self, pidfile):
  20. self.pidfile = pidfile
  21. def get_pid(self):
  22. pidfile_fh = file(self.pidfile, "r")
  23. pid = int(pidfile_fh.read().strip())
  24. pidfile_fh.close()
  25. return pid
  26. def check(self):
  27. if os.path.exists(self.pidfile) and os.path.isfile(self.pidfile):
  28. pid = self.get_pid()
  29. try:
  30. os.kill(pid, 0)
  31. except os.error, e:
  32. if e.errno == errno.ESRCH:
  33. sys.stderr.write("Stale pidfile exists. removing it.\n")
  34. self.remove()
  35. else:
  36. raise SystemExit("celeryd is already running.")
  37. def remove(self):
  38. os.unlink(self.pidfile)
  39. def write(self, pid=None):
  40. if not pid:
  41. pid = os.getpid()
  42. pidfile_fh = file(self.pidfile, "w")
  43. pidfile_fh.write("%d\n" % pid)
  44. pidfile_fh.close()
  45. def remove_pidfile(pidfile):
  46. os.unlink(pidfile)
  47. def daemonize(pidfile):
  48. """Detach a process from the controlling terminal and run it in the
  49. background as a daemon."""
  50. try:
  51. pid = os.fork()
  52. except OSError, e:
  53. raise Exception, "%s [%d]" % (e.strerror, e.errno)
  54. if pid == 0: # child
  55. os.setsid()
  56. try:
  57. pid = os.fork() # second child
  58. except OSError, e:
  59. raise Exception, "%s [%d]" % (e.strerror, e.errno)
  60. if pid == 0: # second child
  61. #os.chdir(DAEMON_WORKDIR)
  62. os.umask(DAEMON_UMASK)
  63. else: # parent (first child)
  64. pidfile.write(pid)
  65. os._exit(0)
  66. else: # root process
  67. os._exit(0)
  68. maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
  69. if (maxfd == resource.RLIM_INFINITY):
  70. maxfd = DAEMON_MAXFD
  71. # Iterate through and close all file descriptors.
  72. for fd in range(0, maxfd):
  73. try:
  74. os.close(fd)
  75. except OSError:
  76. pass
  77. os.open(REDIRECT_TO, os.O_RDWR)
  78. # Duplicate standard input to standard output and standard error.
  79. os.dup2(0, 1)
  80. os.dup2(0, 2)
  81. return 0