From d3f80e8cfd38f8b73cb5f93dbbc64c3aac97fce8 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Thu, 19 Feb 2026 15:57:41 +0100 Subject: [PATCH] fix(ctl): prevent fork deadlock and file watcher triggers Fix two issues with the control socket feature introduced in 25.1.0: 1. Fork deadlock (#3509): The control server runs asyncio in a background thread. When fork() is called to spawn workers, locks held by asyncio can remain locked in the child process, causing deadlocks. Fix by stopping the control server before fork and restarting after fork in the parent. 2. File watcher triggers (#3508): The default socket path `gunicorn.ctl` was created in the app directory, triggering file watchers in dev servers (e.g., GAE dev_appserver). Fix by changing the default path to `/tmp/gunicorn.ctl`. Fixes #3508 Fixes #3509 --- gunicorn/arbiter.py | 7 +++++++ gunicorn/config.py | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index cd838d00..a007f9ef 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -686,11 +686,18 @@ class Arbiter: self.app, self.timeout / 2.0, self.cfg, self.log) self.cfg.pre_fork(self, worker) + + # Stop control server before fork to prevent deadlocks. + # The asyncio thread holds locks that would be stuck in the child. + self._stop_control_server() + pid = os.fork() if pid != 0: worker.pid = pid self.WORKERS[pid] = worker self._stats['workers_spawned'] += 1 + # Restart control server in parent after fork + self._start_control_server() return pid # Do not inherit the temporary files of other workers diff --git a/gunicorn/config.py b/gunicorn/config.py index fa399f03..9fc4603b 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -3123,7 +3123,7 @@ class ControlSocket(Setting): cli = ["--control-socket"] meta = "PATH" validator = validate_string - default = "gunicorn.ctl" + default = "/tmp/gunicorn.ctl" desc = """\ Unix socket path for control interface. @@ -3131,8 +3131,8 @@ class ControlSocket(Setting): ``gunicornc`` command-line tool. Commands include viewing worker status, adjusting worker count, and graceful reload/shutdown. - By default, creates ``gunicorn.ctl`` in the working directory. - Set an absolute path for a fixed location (e.g., ``/var/run/gunicorn.ctl``). + By default, creates ``/tmp/gunicorn.ctl``. Set an absolute path for a + different location (e.g., ``/var/run/gunicorn.ctl``). Use ``--no-control-socket`` to disable.