mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
handle all signals like unicorn or nginx :
http://unicorn.bogomips.org/SIGNALS.html TODO: implementing daemonized mode & config file
This commit is contained in:
parent
786c97442d
commit
4f5548e8bd
@ -49,7 +49,7 @@ class Arbiter(object):
|
|||||||
SIG_QUEUE = []
|
SIG_QUEUE = []
|
||||||
SIGNALS = map(
|
SIGNALS = map(
|
||||||
lambda x: getattr(signal, "SIG%s" % x),
|
lambda x: getattr(signal, "SIG%s" % x),
|
||||||
"CHLD HUP QUIT INT TERM TTIN TTOU".split()
|
"CHLD HUP QUIT INT TERM TTIN TTOU USR1 USR2 WINCH".split()
|
||||||
)
|
)
|
||||||
SIG_NAMES = dict(
|
SIG_NAMES = dict(
|
||||||
(getattr(signal, name), name[3:].lower()) for name in dir(signal)
|
(getattr(signal, name), name[3:].lower()) for name in dir(signal)
|
||||||
@ -82,13 +82,10 @@ class Arbiter(object):
|
|||||||
def signal(self, sig, frame):
|
def signal(self, sig, frame):
|
||||||
if len(self.SIG_QUEUE) < 5:
|
if len(self.SIG_QUEUE) < 5:
|
||||||
self.SIG_QUEUE.append(sig)
|
self.SIG_QUEUE.append(sig)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log.warn("Ignoring rapid signaling: %s" % sig)
|
log.warn("Ignoring rapid signaling: %s" % sig)
|
||||||
|
|
||||||
self.wakeup()
|
self.wakeup()
|
||||||
|
|
||||||
|
|
||||||
def listen(self, addr):
|
def listen(self, addr):
|
||||||
if 'GUNICORN_FD' in os.environ:
|
if 'GUNICORN_FD' in os.environ:
|
||||||
fd = int(os.environ['GUNICORN_FD'])
|
fd = int(os.environ['GUNICORN_FD'])
|
||||||
@ -140,7 +137,6 @@ class Arbiter(object):
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
sig = self.SIG_QUEUE.pop(0) if len(self.SIG_QUEUE) else None
|
sig = self.SIG_QUEUE.pop(0) if len(self.SIG_QUEUE) else None
|
||||||
|
|
||||||
if sig is None:
|
if sig is None:
|
||||||
self.sleep()
|
self.sleep()
|
||||||
continue
|
continue
|
||||||
@ -154,14 +150,12 @@ class Arbiter(object):
|
|||||||
if not handler:
|
if not handler:
|
||||||
log.error("Unhandled signal: %s" % signame)
|
log.error("Unhandled signal: %s" % signame)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
log.info("Handling signal: %s" % signame)
|
log.info("Handling signal: %s" % signame)
|
||||||
handler()
|
handler()
|
||||||
|
|
||||||
self.murder_workers()
|
self.murder_workers()
|
||||||
self.reap_workers()
|
self.reap_workers()
|
||||||
self.manage_workers()
|
self.manage_workers()
|
||||||
|
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
break
|
break
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
@ -174,18 +168,16 @@ class Arbiter(object):
|
|||||||
|
|
||||||
log.info("Master is shutting down.")
|
log.info("Master is shutting down.")
|
||||||
self.stop()
|
self.stop()
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
def handle_chld(self):
|
def handle_chld(self):
|
||||||
self.wakeup()
|
self.wakeup()
|
||||||
|
|
||||||
def handle_hup(self):
|
def handle_hup(self):
|
||||||
log.info("Master hang up.")
|
log.info("Master hang up.")
|
||||||
self.reexec()
|
self.reexec()
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
def handle_quit(self):
|
def handle_quit(self):
|
||||||
self.stop(False)
|
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
def handle_int(self):
|
def handle_int(self):
|
||||||
@ -202,6 +194,19 @@ class Arbiter(object):
|
|||||||
def handle_ttou(self):
|
def handle_ttou(self):
|
||||||
if self.num_workers > 0:
|
if self.num_workers > 0:
|
||||||
self.num_workers -= 1
|
self.num_workers -= 1
|
||||||
|
|
||||||
|
def handle_usr1(self):
|
||||||
|
self.kill_workers(signal.SIGUSR1)
|
||||||
|
|
||||||
|
def handle_usr2(self):
|
||||||
|
self.reexec()
|
||||||
|
|
||||||
|
def handle_winch(self):
|
||||||
|
if os.getppid() == 1 or os.getpgrp() != os.getpid():
|
||||||
|
logger.info("graceful stop of workers")
|
||||||
|
self.kill_workers(True)
|
||||||
|
else:
|
||||||
|
log.info("SIGWINCH ignored. not daemonized")
|
||||||
|
|
||||||
def wakeup(self):
|
def wakeup(self):
|
||||||
# Wake up the arbiter
|
# Wake up the arbiter
|
||||||
@ -228,7 +233,7 @@ class Arbiter(object):
|
|||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
def stop(self, graceful=True):
|
def stop(self, graceful=True):
|
||||||
self.LISTENER.close()
|
self.LISTENER = None
|
||||||
sig = signal.SIGQUIT
|
sig = signal.SIGQUIT
|
||||||
if not graceful:
|
if not graceful:
|
||||||
sig = signal.SIGTERM
|
sig = signal.SIGTERM
|
||||||
@ -241,10 +246,9 @@ class Arbiter(object):
|
|||||||
|
|
||||||
def reexec(self):
|
def reexec(self):
|
||||||
self.reexec_pid = os.fork()
|
self.reexec_pid = os.fork()
|
||||||
if self.reexec_pid != 0:
|
if self.reexec_pid == 0:
|
||||||
os.environ['GUNICORN_FD'] = str(self.LISTENER.fileno())
|
os.environ['GUNICORN_FD'] = str(self.LISTENER.fileno())
|
||||||
self.LISTENER.setblocking(1)
|
os.execlp(sys.argv[0], *sys.argv)
|
||||||
apply(os.execlp, (sys.argv[0],) + tuple(sys.argv))
|
|
||||||
|
|
||||||
def murder_workers(self):
|
def murder_workers(self):
|
||||||
for (pid, worker) in list(self.WORKERS.items()):
|
for (pid, worker) in list(self.WORKERS.items()):
|
||||||
|
|||||||
@ -42,7 +42,7 @@ class Worker(object):
|
|||||||
|
|
||||||
SIGNALS = map(
|
SIGNALS = map(
|
||||||
lambda x: getattr(signal, "SIG%s" % x),
|
lambda x: getattr(signal, "SIG%s" % x),
|
||||||
"HUP QUIT INT TERM TTIN TTOU".split()
|
"HUP QUIT INT TERM TTIN TTOU USR1 USR2".split()
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, workerid, ppid, socket, app):
|
def __init__(self, workerid, ppid, socket, app):
|
||||||
@ -59,6 +59,8 @@ class Worker(object):
|
|||||||
signal.signal(signal.SIGQUIT, self.handle_quit)
|
signal.signal(signal.SIGQUIT, self.handle_quit)
|
||||||
signal.signal(signal.SIGTERM, self.handle_exit)
|
signal.signal(signal.SIGTERM, self.handle_exit)
|
||||||
signal.signal(signal.SIGINT, self.handle_exit)
|
signal.signal(signal.SIGINT, self.handle_exit)
|
||||||
|
signal.signal(signal.SIGUSR1, self.handle_quit)
|
||||||
|
signal.signal(signal.SIGUSR2, self.handle_quit)
|
||||||
|
|
||||||
def handle_quit(self, sig, frame):
|
def handle_quit(self, sig, frame):
|
||||||
self.alive = False
|
self.alive = False
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user