fix(ctl): prevent fork deadlock and file watcher triggers#3520
Open
fix(ctl): prevent fork deadlock and file watcher triggers#3520
Conversation
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
|
Just tested this fix in my CI jobs which were blocked using 25.1.0 release. gevent worker class, 1 worker:
|
pajod
reviewed
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 : Happy to validate a release with this patch in our CI/runtime path. |
This was referenced Feb 26, 2026
- 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
Owner
Author
|
@kaxil latest should fix it |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.ctlin app directory triggers file watchers (e.g., GAE dev_appserver) causing restart loops. Fix: change default to/tmp/gunicorn.ctl.Fixes #3508
Fixes #3509