From 866d1e71900fc395a50340dc2ecc645782ad24c5 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 17 May 2018 12:51:29 +0200 Subject: [PATCH] [FIX] server: fix support for systemd socket activation in threaded server This patches fixes the untested and broken draft of inetd and systemd activation support in the threaded server. This patch also fixes the loss of the process environment in the `_reexec()` function when Odoo is respawning during the following events: - SIGHUP signal is received - one click install has been triggered - code reload needed when using `--dev=reload` --- openerp/service/server.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/openerp/service/server.py b/openerp/service/server.py index c3baace20dc..af01ea9d54f 100644 --- a/openerp/service/server.py +++ b/openerp/service/server.py @@ -91,9 +91,6 @@ class RequestHandler(werkzeug.serving.WSGIRequestHandler): me = threading.currentThread() me.name = 'openerp.service.http.request.%s' % (me.ident,) -# _reexec() should set LISTEN_* to avoid connection refused during reload time. It -# should also work with systemd socket activation. This is currently untested -# and not yet used. class ThreadedWSGIServerReloadable(LoggingBaseWSGIServerMixIn, werkzeug.serving.ThreadedWSGIServer): """ werkzeug Threaded WSGI Server patched to allow reusing a listen socket @@ -105,14 +102,15 @@ class ThreadedWSGIServerReloadable(LoggingBaseWSGIServerMixIn, werkzeug.serving. handler=RequestHandler) def server_bind(self): - envfd = os.environ.get('LISTEN_FDS') - if envfd and os.environ.get('LISTEN_PID') == str(os.getpid()): + SD_LISTEN_FDS_START = 3 + if os.environ.get('LISTEN_FDS') == '1' and os.environ.get('LISTEN_PID') == str(os.getpid()): self.reload_socket = True - self.socket = socket.fromfd(int(envfd), socket.AF_INET, socket.SOCK_STREAM) - # should we os.close(int(envfd)) ? it seem python duplicate the fd. + self.socket = socket.fromfd(SD_LISTEN_FDS_START, socket.AF_INET, socket.SOCK_STREAM) + _logger.info('HTTP service (werkzeug) running through socket activation') else: self.reload_socket = False super(ThreadedWSGIServerReloadable, self).server_bind() + _logger.info('HTTP service (werkzeug) running on %s:%s', self.server_name, self.server_port) def server_activate(self): if not self.reload_socket: @@ -254,7 +252,6 @@ class ThreadedServer(CommonServer): t = threading.Thread(target=self.http_thread, name="openerp.service.httpd") t.setDaemon(True) t.start() - _logger.info('HTTP service (werkzeug) running on %s:%s', self.interface, self.port) def start(self, stop=False): _logger.debug("Setting signal handlers") @@ -853,7 +850,8 @@ def _reexec(updated_modules=None): args += ["-u", ','.join(updated_modules)] if not args or args[0] != exe: args.insert(0, exe) - os.execv(sys.executable, args) + # We should keep the LISTEN_* environment variabled in order to support socket activation on reexec + os.execve(sys.executable, args, os.environ) def load_test_file_yml(registry, test_file): with registry.cursor() as cr: