From 272d905f0026edb54a3d35407fbfbca6185bc39e 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 a2a720657..7ef5c7129 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__) @@ -236,6 +236,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 00668f890..0b62f381f 100644 --- a/server_environment/system_info.py +++ b/server_environment/system_info.py @@ -7,11 +7,25 @@ import platform import subprocess +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 @@ -20,6 +34,9 @@ def _get_output(cmd): 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")