Created
January 23, 2014 04:25
-
-
Save sp3c73r2038/8572807 to your computer and use it in GitHub Desktop.
handle signal using a queue, stolen from unicorn :)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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