Merge pull request #1090 from yunstanford/patch-signal-handling

Patch signal handling
This commit is contained in:
Raphael Deem 2018-01-20 14:03:23 -08:00 committed by GitHub
commit f3bf5e9a5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 12 deletions

View File

@ -5,7 +5,7 @@ from functools import partial
from inspect import isawaitable from inspect import isawaitable
from multiprocessing import Process from multiprocessing import Process
from signal import ( from signal import (
SIGTERM, SIGINT, SIGTERM, SIGINT, SIG_IGN,
signal as signal_func, signal as signal_func,
Signals Signals
) )
@ -20,9 +20,10 @@ from httptools import HttpRequestParser
from httptools.parser.errors import HttpParserError from httptools.parser.errors import HttpParserError
try: try:
import uvloop as async_loop import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
except ImportError: except ImportError:
async_loop = asyncio pass
from sanic.log import logger, access_logger from sanic.log import logger, access_logger
from sanic.response import HTTPResponse from sanic.response import HTTPResponse
@ -509,11 +510,11 @@ def serve(host, port, request_handler, error_handler, before_start=None,
request_timeout=60, response_timeout=60, keep_alive_timeout=5, request_timeout=60, response_timeout=60, keep_alive_timeout=5,
ssl=None, sock=None, request_max_size=None, reuse_port=False, ssl=None, sock=None, request_max_size=None, reuse_port=False,
loop=None, protocol=HttpProtocol, backlog=100, loop=None, protocol=HttpProtocol, backlog=100,
register_sys_signals=True, run_async=False, connections=None, register_sys_signals=True, run_multiple=False, run_async=False,
signal=Signal(), request_class=None, access_log=True, connections=None, signal=Signal(), request_class=None,
keep_alive=True, is_request_stream=False, router=None, access_log=True, keep_alive=True, is_request_stream=False,
websocket_max_size=None, websocket_max_queue=None, state=None, router=None, websocket_max_size=None, websocket_max_queue=None,
graceful_shutdown_timeout=15.0): state=None, graceful_shutdown_timeout=15.0):
"""Start asynchronous HTTP Server on an individual process. """Start asynchronous HTTP Server on an individual process.
:param host: Address to host on :param host: Address to host on
@ -547,7 +548,8 @@ def serve(host, port, request_handler, error_handler, before_start=None,
:return: Nothing :return: Nothing
""" """
if not run_async: if not run_async:
loop = async_loop.new_event_loop() # create new event_loop after fork
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)
if debug: if debug:
@ -603,9 +605,14 @@ def serve(host, port, request_handler, error_handler, before_start=None,
trigger_events(after_start, loop) trigger_events(after_start, loop)
# Ignore SIGINT when run_multiple
if run_multiple:
signal_func(SIGINT, SIG_IGN)
# Register signals for graceful termination # Register signals for graceful termination
if register_sys_signals: if register_sys_signals:
for _signal in (SIGINT, SIGTERM): _singals = (SIGTERM,) if run_multiple else (SIGINT, SIGTERM)
for _signal in _singals:
try: try:
loop.add_signal_handler(_signal, loop.stop) loop.add_signal_handler(_signal, loop.stop)
except NotImplementedError: except NotImplementedError:
@ -668,6 +675,7 @@ def serve_multiple(server_settings, workers):
:return: :return:
""" """
server_settings['reuse_port'] = True server_settings['reuse_port'] = True
server_settings['run_multiple'] = True
# Handling when custom socket is not provided. # Handling when custom socket is not provided.
if server_settings.get('sock') is None: if server_settings.get('sock') is None:
@ -682,12 +690,13 @@ def serve_multiple(server_settings, workers):
def sig_handler(signal, frame): def sig_handler(signal, frame):
logger.info("Received signal %s. Shutting down.", Signals(signal).name) logger.info("Received signal %s. Shutting down.", Signals(signal).name)
for process in processes: for process in processes:
os.kill(process.pid, SIGINT) os.kill(process.pid, SIGTERM)
signal_func(SIGINT, lambda s, f: sig_handler(s, f)) signal_func(SIGINT, lambda s, f: sig_handler(s, f))
signal_func(SIGTERM, lambda s, f: sig_handler(s, f)) signal_func(SIGTERM, lambda s, f: sig_handler(s, f))
processes = [] processes = []
for _ in range(workers): for _ in range(workers):
process = Process(target=serve, kwargs=server_settings) process = Process(target=serve, kwargs=server_settings)
process.daemon = True process.daemon = True

View File

@ -23,4 +23,3 @@ def test_multiprocessing():
app.run(HOST, app.test_port, workers=num_workers) app.run(HOST, app.test_port, workers=num_workers)
assert len(process_list) == num_workers assert len(process_list) == num_workers