From a5d01ccb4798e2df85976843bcbd0f278bb1a173 Mon Sep 17 00:00:00 2001 From: David Gallay Date: Wed, 24 Jun 2026 11:42:19 +0200 Subject: [PATCH] [FIX] server_environment: fix deadlock between gevent and subprocesses Call to `subprocess.Popen` caused a deadlock. This broke the gevent worker when `workers > 0`. As a consequence, the port 8072 supposed to handle /websocket never responds. Gevent warns against it on startup: > gevent/os.py:426: DeprecationWarning: This process is multi-threaded, use of fork() may lead to deadlocks in the child. --- server_environment/server_env.py | 4 +++- server_environment/system_info.py | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/server_environment/server_env.py b/server_environment/server_env.py index ad76e3410..0a0dd96df 100644 --- a/server_environment/server_env.py +++ b/server_environment/server_env.py @@ -14,7 +14,7 @@ from odoo.addons.base_sparse_field.models.fields import Serialized -from .system_info import get_server_environment +from .system_info import get_server_environment, skip_subprocess _logger = logging.getLogger(__name__) @@ -246,6 +246,8 @@ def _get_env_cols(cls, sections=None): @classmethod def _get_system_cols(cls): """Compute system fields""" + if skip_subprocess(): + return {} res = {} for col, item in get_server_environment(): key = cls._format_key("system", col) diff --git a/server_environment/system_info.py b/server_environment/system_info.py index 9b303e849..51ccbd749 100644 --- a/server_environment/system_info.py +++ b/server_environment/system_info.py @@ -8,11 +8,25 @@ import subprocess from functools import lru_cache +import odoo from odoo import release from odoo.tools.config import config +def skip_subprocess(): + # In the gevent worker (longpolling/websocket) running subprocesses can + # deadlock, freezing real-time updates. This system info only feeds the + # settings display, so skip the subprocess calls there. + return odoo.evented + + def _get_output(cmd): + # Use assert to force developers to + # take correct action when developing + # but running `python -O` removes it completely + assert ( + not skip_subprocess() + ), "Subprocess must not be called, use skip_subprocess in a pre-check" bindir = config["root_path"] p = subprocess.Popen( cmd, shell=True, cwd=bindir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT @@ -22,6 +36,9 @@ def _get_output(cmd): @lru_cache(maxsize=1) def get_server_environment(): + # Function relies mainly on subprocesses + if skip_subprocess(): + return () # inspired by server/bin/service/web_services.py try: rev_id = "git:%s" % _get_output("git rev-parse HEAD")