From 8a279675254b4a157a41512b5418cda149d40079 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 21 Jan 2013 16:35:40 +0100 Subject: [PATCH] [IMP] oe web: handle SIGINT and somewhat SIGTERM for the gevent case. bzr revid: vmt@openerp.com-20130121153540-wnlnz7u8ypwg165i --- openerp/cli/server.py | 8 ++++---- openerpcommand/cron.py | 2 +- openerpcommand/web.py | 44 +++++++++++++++++++++++++++++++++--------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/openerp/cli/server.py b/openerp/cli/server.py index 7fb252f905f..2408703d6b8 100644 --- a/openerp/cli/server.py +++ b/openerp/cli/server.py @@ -181,9 +181,9 @@ def dumpstacks(sig, frame): code.append(" %s" % (line.strip())) _logger.info("\n".join(code)) -def setup_signal_handlers(): - """ Register the signal handler defined above. """ - SIGNALS = map(lambda x: getattr(signal, "SIG%s" % x), "INT TERM".split()) +def setup_signal_handlers(signal_handler): + """ Register the given signal handler. """ + SIGNALS = (signal.SIGINT, signal.SIGTERM) if os.name == 'posix': map(lambda sig: signal.signal(sig, signal_handler), SIGNALS) signal.signal(signal.SIGQUIT, dumpstacks) @@ -238,7 +238,7 @@ def main(args): configure_babel_localedata_path() - setup_signal_handlers() + setup_signal_handlers(signal_handler) if config["test_file"]: run_test_file(config['db_name'], config['test_file']) diff --git a/openerpcommand/cron.py b/openerpcommand/cron.py index 441cc48d457..16b983dbc50 100644 --- a/openerpcommand/cron.py +++ b/openerpcommand/cron.py @@ -26,7 +26,7 @@ def run(args): openerp.netsvc.init_logger() #openerp.cli.server.report_configuration() openerp.cli.server.configure_babel_localedata_path() - openerp.cli.server.setup_signal_handlers() + openerp.cli.server.setup_signal_handlers(openerp.cli.server.signal_handler) import openerp.addons.base if args.database: for db in args.database: diff --git a/openerpcommand/web.py b/openerpcommand/web.py index 7c39d8ecdc6..728318d1d9f 100644 --- a/openerpcommand/web.py +++ b/openerpcommand/web.py @@ -4,13 +4,36 @@ Run a normal OpenERP HTTP process. import logging import os -import threading +import signal import common _logger = logging.getLogger(__name__) +def mk_signal_handler(server): + def signal_handler(sig, frame): + """ + Specialized signal handler for the evented process. + """ + print "\n\n\nStopping gevent HTTP server...\n\n\n" + server.stop() + return signal_handler + +def setup_signal_handlers(signal_handler): + SIGNALS = (signal.SIGINT, signal.SIGTERM) + map(lambda sig: signal.signal(sig, signal_handler), SIGNALS) + def run(args): + # Note that gevent monkey patching must be done before importing the + # `threading` module, see http://stackoverflow.com/questions/8774958/. + if args.gevent: + import gevent + import gevent.monkey + import gevent.wsgi + import gevent_psycopg2 + gevent.monkey.patch_all() + gevent_psycopg2.monkey_patch() + import threading import openerp import openerp.cli.server import openerp.service.wsgi_server @@ -27,11 +50,11 @@ def run(args): openerp.netsvc.init_logger() #openerp.cli.server.report_configuration() openerp.cli.server.configure_babel_localedata_path() - openerp.cli.server.setup_signal_handlers() target = openerp.service.wsgi_server.serve if not args.gevent: openerp.evented = False + openerp.cli.server.setup_signal_handlers(openerp.cli.server.signal_handler) # TODO openerp.multi_process with a multi-threaded process probably # doesn't work very well (e.g. waiting for all threads to complete # before killing the process is not implemented). @@ -40,16 +63,19 @@ def run(args): openerp.cli.server.quit_on_signals() else: openerp.evented = True - import gevent.monkey - import gevent.wsgi - import gevent_psycopg2 - gevent.monkey.patch_all() - gevent_psycopg2.monkey_patch() app = openerp.service.wsgi_server.application server = gevent.wsgi.WSGIServer((args.interface, int(args.port)), app) - server.serve_forever() - # TODO quit_on_signals + setup_signal_handlers(mk_signal_handler(server)) + try: + server.serve_forever() + except KeyboardInterrupt: + try: + server.stop() + gevent.shutdown() + except KeyboardInterrupt: + sys.stderr.write("Forced shutdown.\n") + gevent.shutdown() def add_parser(subparsers): parser = subparsers.add_parser('web',