put pidfile funcs in object on suggestion from davisp "but that's a

simple change"
This commit is contained in:
benoitc 2010-05-09 01:49:24 +02:00
parent cbd91309fe
commit 87760fe750
2 changed files with 64 additions and 56 deletions

View File

@ -15,7 +15,7 @@ import sys
import time import time
import traceback import traceback
from gunicorn.pidfile import set_pidfile, unlink_pidfile from gunicorn.pidfile import Pidfile
from gunicorn.sock import create_socket from gunicorn.sock import create_socket
from gunicorn.workers.sync import SyncWorker from gunicorn.workers.sync import SyncWorker
from gunicorn import util from gunicorn import util
@ -92,7 +92,8 @@ class Arbiter(object):
self.pid = os.getpid() self.pid = os.getpid()
self.init_signals() self.init_signals()
self.LISTENER = create_socket(self.cfg) self.LISTENER = create_socket(self.cfg)
self.pidfile = set_pidfile(self.pid, self.cfg.pidfile, self.pidfile) self.pidfile = Pidfile(self.cfg.pidfile)
self.pidfile.create(self.pid)
self.log.info("Arbiter booted") self.log.info("Arbiter booted")
self.log.info("Listening at: %s" % self.LISTENER) self.log.info("Listening at: %s" % self.LISTENER)
@ -152,14 +153,14 @@ class Arbiter(object):
self.log.info("Unhandled exception in main loop:\n%s" % self.log.info("Unhandled exception in main loop:\n%s" %
traceback.format_exc()) traceback.format_exc())
self.stop(False) self.stop(False)
if self.pidfile: if self.pidfile is not None:
unlink_pidfile(self.pid, self.pidfile) self.pidfile.unlink()
sys.exit(-1) sys.exit(-1)
self.stop() self.stop()
self.log.info("Shutting down: %s" % self.master_name) self.log.info("Shutting down: %s" % self.master_name)
if self.pidfile: if self.pidfile is not None:
unlink_pidfile(self.pid, self.pidfile) self.pidfile.unlink()
sys.exit(0) sys.exit(0)
def handle_chld(self, sig, frame): def handle_chld(self, sig, frame):
@ -285,9 +286,8 @@ class Arbiter(object):
"""\ """\
Relaunch the master and workers. Relaunch the master and workers.
""" """
if self.pidfile: if self.pidfile is not None:
old_pidfile = "%s.oldbin" % self.pidfile self.pidfile.rename("%s.oldbin" % self.pidfile.path)
self.pidfile = set_pidfile(self.pid, old_pidfile)
self.reexec_pid = os.fork() self.reexec_pid = os.fork()
if self.reexec_pid != 0: if self.reexec_pid != 0:

View File

@ -10,52 +10,60 @@ import os
import tempfile import tempfile
def set_pidfile(pid, path, oldpath=None): class Pidfile(object):
oldpid = valid_pidfile(path)
if oldpid:
if oldpath is not None and path == oldpath and \
oldpid == os.getpid():
return path
raise RuntimeError("Already running on PID %s " \
"(or pid file '%s' is stale)" % (os.getpid(), path))
if oldpath:
unlink_pidfile(pid, path)
# write pidfile
fd, fname = tempfile.mkstemp(dir=os.path.dirname(path))
os.write(fd, "%s\n" % pid)
os.rename(fname, path)
os.close(fd)
return path
def unlink_pidfile(pid, path): def __init__(self, path):
""" delete pidfile""" self.path = path
try: self.pid = None
with open(path, "r") as f:
pid1 = int(f.read() or 0) def create(self, pid):
oldpid = self.validate()
if pid1 == pid: if oldpid:
os.unlink(path) if oldpid == os.getpid():
except: return
pass raise RuntimeError("Already running on PID %s " \
"(or pid file '%s' is stale)" % (os.getpid(), self.path))
def valid_pidfile(path):
""" Validate pidfile and make it stale if needed"""
try:
with open(path, "r") as f:
wpid = int(f.read() or 0)
if wpid <= 0: return None self.pid = pid
try: # write pidfile
os.kill(wpid, 0) fd, fname = tempfile.mkstemp(dir=os.path.dirname(self.path))
return wpid os.write(fd, "%s\n" % self.pid)
except OSError, e: os.rename(fname, self.path)
if e[0] == errno.ESRCH: os.close(fd)
return
raise def rename(self, path):
except IOError, e: self.unlink()
if e[0] == errno.ENOENT: self.path = path
return self.create(self.pid)
raise
def unlink(self):
""" delete pidfile"""
try:
with open(self.path, "r") as f:
pid1 = int(f.read() or 0)
if pid1 == self.pid:
os.unlink(self.path)
except:
pass
def validate(self):
""" Validate pidfile and make it stale if needed"""
try:
with open(self.path, "r") as f:
wpid = int(f.read() or 0)
if wpid <= 0: return None
try:
os.kill(wpid, 0)
return wpid
except OSError, e:
if e[0] == errno.ESRCH:
return
raise
except IOError, e:
if e[0] == errno.ENOENT:
return
raise