-
-
Notifications
You must be signed in to change notification settings - Fork 743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix uvicorn gunicorn worker class restarts when USR1 is issued #1565
Fix uvicorn gunicorn worker class restarts when USR1 is issued #1565
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't test locally, but the lines here are the same as the parent class, so it should be fine.
Ref.: https://github.com/benoitc/gunicorn/blob/027f04b4b4aee4f50b980a7158add0feaf4c1b29/gunicorn/workers/base.py#L167-L182
I'll test locally later today in case @euri10 doesn't do it first. 👀
uvicorn/workers.py
Outdated
@@ -72,6 +72,11 @@ def init_signals(self) -> None: | |||
for s in self.SIGNALS: | |||
signal.signal(s, signal.SIG_DFL) | |||
|
|||
# Remove me if SIGUSR1 is handled in server.py |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't get this comment here... This doesn't affect uvicorn
standalone. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was referring to the comment from tiangolo.
This is because the UvicornWorker, which inherits from the base Gunicorn worker, declares a method init_signals() (overriding the parent method) but doesn't do anything. I suspect it's because the signal handlers are declared in the Server.install_signal_handlers() with compatibility with asyncio.
But you are right, I was thinking that install_signal_handlers() in server.py could call init_signal in future. But this is unlikely as init_signal (esp signal.signal) isn't compatible with asyncio. I will remove this comment. 03a57af
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @wonjoonSeol-WS 🙏
…e#1565) * Fix uvicorn gunicorn worker class restarts when USR1 is issued * Remove comment
* Fix uvicorn gunicorn worker class restarts when USR1 is issued * Remove comment
Copied from my original post #1559 (comment)
Steps to reproduce
Minimal Fastapi code
Run with gunicorn
gunicorn -w 1 -k uvicorn.workers.UvicornWorker --pid /tmp/log/gunicorn.pid main:app
Set up logging
Set up logrotate
/etc/logrotate.d/uvicorn-test
Send USR1 signal
kill -USR1 $(cat /tmp/log/gunicorn.pid)
or force logrotate
sudo logrotate --force /etc/logrotate.d/uvicorn-test
We can see the process is terminated:
Proposal: Change uvicorn/worker.py to the following code:
Re-run test
Process is no longer terminated, logrotates fine and log.txt is still appended after the file rotation.
Clearly this change only impacts Uvicorn's gunicorn worker class. i.e.
kill -USR1 pid
after running it with uvicorn only(
uvicorn --host 0.0.0.0 --port 8000 main:app
), the worker is still terminated even with the work above.But
USR1: Reopen the log files
behaviour is only documented on Gunicorn and undocumented on Uvicorn master (yet) so this could be expected behaviour(?). Otherwise we would need to create an async version ofhandle_usr1
method inserver.py
.Btw, we can't simply fully copy gunicorn's init_signals method as suggested by yinkh in #896 (comment)
As the below signals are not compatible with asyncio.
We would end up with errors like below.
Testing other signals such as TTIN, TTOU, QUIT, INT, TERM on gunicorn's signal handling page (https://docs.gunicorn.org/en/stable/signals.html) seem to work fine.
I have no idea if these two lines from gunicorn worker base class https://github.com/benoitc/gunicorn/blob/027f04b4b4aee4f50b980a7158add0feaf4c1b29/gunicorn/workers/base.py#L185
are needed though. It seem to work fine without it. So I excluded it for now:
Thanks.