Skip to content

fix(ctl): prevent fork deadlock and file watcher triggers#3520

Open
benoitc wants to merge 4 commits intomasterfrom
fix/control-socket-issues
Open

fix(ctl): prevent fork deadlock and file watcher triggers#3520
benoitc wants to merge 4 commits intomasterfrom
fix/control-socket-issues

Conversation

@benoitc
Copy link
Owner

@benoitc benoitc commented Feb 19, 2026

Summary

Fixes two issues with the control socket feature introduced in 25.1.0:

Fork deadlock (#3509): Control server runs asyncio in a background thread. When fork() spawns workers, locks held by asyncio remain locked in child → deadlock. Fix: stop control server before fork, restart after in parent.

File watcher triggers (#3508): Default socket path gunicorn.ctl in app directory triggers file watchers (e.g., GAE dev_appserver) causing restart loops. Fix: change default to /tmp/gunicorn.ctl.

Fixes #3508
Fixes #3509

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
@fcharlier
Copy link

Just tested this fix in my CI jobs which were blocked using 25.1.0 release.

gevent worker class, 1 worker:

  • no worker booted with 25.1.0
  • worker booted correctly with 25.1.0 and --no-control-socket
  • worker booted correctly with this fix and control socket enabled (or rather not disabled)

@kaxil
Copy link

kaxil commented Feb 26, 2026

Thanks for this fix.

We hit the same startup deadlock pattern in Apache Airflow's Gunicorn API-server path (preload + fork + uvicorn worker).

In our environment:

Details and stack excerpts are in :
#3529

Happy to validate a release with this patch in our CI/runtime path.

- Use os.register_at_fork() to properly handle fork() with asyncio
- Start control server after initial workers spawn, not before
- Change default socket path to /run/gunicorn.ctl (like BIRD)
- Add integration tests for sync, gthread, and gevent workers

Fixes #3509
- Replace global statement with module-level dict in ctl/server.py
- Fix argument rename warning in gtornado.py nested class method
@benoitc
Copy link
Owner Author

benoitc commented Feb 27, 2026

@kaxil latest should fix it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants