-
-
Notifications
You must be signed in to change notification settings - Fork 753
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
Cooperative signal handling #1600
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Hey @maxfischer2781 , I wonder if your PR would make this PR #1768 unnecessary? |
Yes, I think ur implementation is better and involves less magic |
It may be nice to add a test covering |
@JoanFM Possibly, but the two changes have slightly different behaviour. This PR will trigger the original handler after the univocrn shutdown procedure. #1768 will trigger the original handler before the uvicorn shutdown procedure. As a default, I think triggering the original handlers late is better – many handlers shutdown quickly (namely, the default handlers) and would skip the uvicorn shutdown entirely. It might be worth having a method to chain handlers explicitly, though. |
Yes, plus your PR does not use any private function and would work with more One question I have, will this PR respect the signals passed to an loop.add_signal_handler(...) instead of signal.signal(...) ? |
Sadly it won't. There is no clean way to query the loop for registered handlers – handlers are stored in a private attribute of the loop and methods allow only to set or delete handlers by signal number. |
Okey, but signal.signal should work the same except if I need to interact with event loop itself. Any idea when this might be merged? |
Is it me, or this question sounds a bit presumptious? 😅 Thanks for the PR @maxfischer2781 , and sorry the delay. This requires a bit of my focus, as there are many ideias related around. I'll check the whole signal thingy for 0.23.0. I'm about to release 0.22.0. No estimation can be provided, since I work on uvicorn on my free time. |
Sorry @Kludex, No bad intentions in this question. I really appreciate the work you guys do and understand it is not easy to dedicate time. I just do not know how this specific project worked. Thanks for everything |
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.
Does this solve #1301 as well?
Ok, review done. Happy new year! 😎
Relevant: #1708 |
@Kludex I've addressed/implemented all suggestions now. Please take another look once you find the time. I don't think an approach as suggested in #1708 makes sense in uvicorn: Practically, signal handling is a two-step approach of 1) handling the signal and setting the shutdown flag and 2) actually shutting down the server. That means one cannot run a "regular" signal handler before or after the uvicorn signal handler (1), since one needs to wait for the server to shut down (2) first. |
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'll check this better later on.
5255717
to
aa44f36
Compare
@Kludex Do you still see any required changes? As far as I can tell I should have everything covered. |
@Kludex It would be super to see this merged! 🙏 |
@maxfischer2781 thanks for your work on this. Since you opened the PR, we've added a PR template with a checklist. For your PR, I think it would currently look like this:
So it seems like what's missing is some documentation of the server's signal handling behavior. We have a docs page on server behavior that could work for this (it's here in the repo code). If you could add a section there and clearly explain how signal handling will work after this PR, I think it would help everyone understand this better. After some docs are added to explain the signal handling behavior, I'm happy to give this PR a review as well. |
@br3ndonland Thanks for the reply, I'll prepare proper docs. Can you give me some input on things I would change for making this "official" via documentation:
|
Sure! This PR is about running the server programmatically, so either the server behavior page or the deployment docs on running programmatically could work. Thanks for the suggestion.
You make a good point here. I agree that the implementation should be as portable and consistent as possible, but given the long discussion in this PR and in #1579, it might be most pragmatic to keep the existing behavior as-is and just document it. I'm happy to take a look at the code either way. |
Has it been decided to leave the broken behaviour? |
I'm still committed to finishing this but seeing how long this dragged on my initial time window for working on it is gone. It may take about 1-4 weeks until I have time to work on this again. |
Thanks for not giving up @maxfischer2781 🙏 I'll make a release shortly. |
In Falcon's test suite, we used to check the return code for functional tests of ASGI servers. Since we terminate the server via |
3221225786 is the unsigned interpretation of Windows' |
I see, thanks @maxfischer2781! |
Please tell me, is this the expected behavior after this pull request? main.py async def app(scope, receive, send):
assert scope['type'] == 'http'
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
[b'content-type', b'text/plain'],
],
})
await send({
'type': 'http.response.body',
'body': b'Hello, world!',
}) uvicorn 0.28.0
uvicorn 0.29.0
non zero return code |
Yes, this is expected. Notice that 143 is 128+15, bash's way of saying the program was killed by signal 15 - i.e. exactly what you requested with |
@maxfischer2781 Are you able to run |
Thanks for the answer I was a little confused, because I was used to SIGTERM being a regular program termination mechanism and expecting a return code of 0, that everything is fine, now we get a non-zero return code, maybe this will break someone's work under supervisors |
@Kludex The tests are working for me locally, but that's MacOS. Windows might be behaving differently again sigh. If you have any leads that there is a problem, can you open a ticket and ping me? I'll have a look then. |
I use MacOS as well. Did you run only that file? |
Now I did. I can confirm that running the tests in isolation makes them fail due to an unhandled What's weird is that the full test suite runs the Edit: Just running both Edit: Running any of the other supervisor tests is sufficient to hide the failure. I'm guessing this is because they all install custom signal handlers but do not remove them. As far as I can tell there are three related "issues" here:
My guess is that this may be hiding a veritable error but I need to double-check that. I'll start by fixing 2 and working up from there, even if it just means we can rely on the tests again. |
Hi Max @maxfischer2781 , I would greatly appreciate your advices on the following. Context:
Questions:
Thanks in advance! |
@bekoev The behaviour is harmless and intentional, but it's been raised as annoying and misleading multiple times now. So this will likely be made less noisy in the future. |
This PR adjust the signal handling of
uvicorn.server.Server
to integrate withasyncio
applications by not suppressing shutdown signals. Major changes include:Server.serve
finishesIn the usual case, this allows CTRL+C to end both
uvicorn
and the containing async application. Closes #1579.There is a caveat for tests in that signal handling on Windows is not as precise as on Unix (see e.g. Stackoverflow: How to handle a signal.SIGINT on a Windows OS machine?). For testing, I could not setup a situation where the tests receive a signal without the test environment also being interrupted by it.