Skip to content

Instantly share code, notes, and snippets.

@sp3c73r2038
Created January 23, 2014 04:25
Show Gist options
  • Save sp3c73r2038/8572807 to your computer and use it in GitHub Desktop.
Save sp3c73r2038/8572807 to your computer and use it in GitHub Desktop.
handle signal using a queue, stolen from unicorn :)
#!/usr/bin/env python
import errno
from fcntl import fcntl, F_SETFL
import os
from select import select
from signal import signal, SIGQUIT, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGHUP
from time import sleep
class Server(object):
QUEUE_SIGS = [SIGQUIT, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGHUP]
EXIT_SIGS = [SIGQUIT, SIGTERM, SIGINT]
def __init__(self):
self.SIG_QUEUE = []
# the main point of sig queue is this pair of pipe
# using system call pipe(2), for more info see pipe(7)
self.pipes = os.pipe()
for fd in self.pipes:
fcntl(fd, F_SETFL, os.O_NONBLOCK)
self._r = os.fdopen(self.pipes[0], 'r')
self._w = os.fdopen(self.pipes[1], 'w')
def start(self):
def queue_sig(sig, frames):
self.SIG_QUEUE.append(sig)
self.awaken()
for sig in self.QUEUE_SIGS:
# handle all sig in this func
signal(sig, queue_sig)
return self
def awaken(self):
"""write to w pipe to activate the select"""
self._w.write('.')
self._w.flush()
def join(self):
while True:
print(self.SIG_QUEUE)
if len(self.SIG_QUEUE) > 0:
# signal handling
sig = self.SIG_QUEUE.pop(0)
if sig in [SIGQUIT, SIGINT, SIGTERM]:
print('quit')
return
elif sig == SIGHUP:
print('hup: reload config')
elif sig == SIGUSR1:
print('usr1')
elif sig == SIGUSR2:
print('usr2')
else:
self.master_sleep()
def master_sleep(self):
try:
# once the r pipe is ready, master will be activated
r, _, _ = select([self.pipes[0]], [], [], 5)
print(r)
if r and r[0] == self.pipes[0]:
# we must read it, or it will cause r pipe stay in
# ready status for ever !
print(self._r.read(1024))
except InterruptedError as e:
# handle awkward EINTR in select, even though we've made
# handler to capture SIGINT
if e.errno == errno.EINTR:
pass
else:
import traceback
traceback.print_exc()
s = Server()
s.start().join()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment