From 03e47dd6fff0b2efa7f262feb776d2bd13c8dc3d Mon Sep 17 00:00:00 2001 From: tsm-odoo Date: Thu, 8 Sep 2022 14:51:27 +0000 Subject: [PATCH] [FIX] bus: fix interface error on server stop When stopping the server, all cursors are closed. The issue is that the ImDispatch thread is kept alive until the main thread exits. This can lead to errors during server stop: the ImDispatch thread could try to poll an already closed connection thus raising a `psycopg2.InterfaceError` exception. This commit solves the issue by hiding the interface error when it occurs during server stop. closes odoo/odoo#100002 X-original-commit: 83777078f1be093c218267c8282e8c11f4fb4e8d Signed-off-by: Julien Castiaux --- addons/bus/models/bus.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/bus/models/bus.py b/addons/bus/models/bus.py index fdc62b4dca0..552e45f4aff 100644 --- a/addons/bus/models/bus.py +++ b/addons/bus/models/bus.py @@ -6,9 +6,11 @@ import random import selectors import threading import time +from psycopg2 import InterfaceError import odoo from odoo import api, fields, models +from odoo.service.server import CommonServer from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT from odoo.tools import date_utils @@ -150,7 +152,7 @@ class ImDispatch(threading.Thread): cr.commit() conn = cr._cnx sel.register(conn, selectors.EVENT_READ) - while True: + while not stop_event.is_set(): if sel.select(TIMEOUT): conn.poll() channels = [] @@ -165,14 +167,18 @@ class ImDispatch(threading.Thread): websocket.trigger_notification_dispatching() def run(self): - while True: + while not stop_event.is_set(): try: self.loop() - except Exception: + except Exception as exc: + if isinstance(exc, InterfaceError) and stop_event.is_set(): + continue _logger.exception("Bus.loop error, sleep and retry") time.sleep(TIMEOUT) dispatch = None +stop_event = threading.Event() if not odoo.multi_process or odoo.evented: # We only use the event dispatcher in threaded and gevent mode dispatch = ImDispatch() + CommonServer.on_stop(stop_event.set)