-
-
Notifications
You must be signed in to change notification settings - Fork 764
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
uvicorn eats SIGINTs, does not propagate exceptions #1579
Comments
I saw this getting flagged by SonarQube. # h11_impl.py line 401
async def run_asgi(self, app: "ASGI3Application") -> None:
try:
result = await app(self.scope, self.receive, self.send)
except BaseException as exc:
msg = "Exception in ASGI application\n"
self.logger.error(msg, exc_info=exc)
if not self.response_started:
await self.send_500_response()
else:
self.transport.close() There are multiple instances of it in other files as well. Sonar:
|
I'm having trouble with the '--reload' option inside docker. Nothing reloads. I suspect it might be related to this. I've tried running uvicorn via the watchfiles cli, and SIGINTs get swallowed. |
Here's a very hacky workaround from uvicorn import Server
class MyCustomUvicornServer(Server):
def install_signal_handlers(self):
pass |
Well, for my problem I've uninstalled watchfiles so uvicorn falls back to polling which works. |
This has turned out to be a real problem for running an optional It looks okay'ish for |
Yes. Running into this exact scenario at the moment: I'm wrapping |
This has caused us some weird problems at Prefect as well. Most recently, I've worked around it with funky usage of a cancel scope but this took a lot of trial and error to get working at all. Would it be feasible to merge something like #1600 or is there interest in a different |
^ courtesy ping for @Kludex , who seems to be the most active maintainer |
I have the same problem, I wonder if |
What's the problem with the following? import asyncio
from starlette.applications import Starlette
from uvicorn import Config, Server
async def web_ui():
print("Inside web_ui")
await Server(Config(Starlette())).serve()
async def sleep():
try:
print("Inside task")
await asyncio.sleep(100000000000000)
except asyncio.CancelledError:
print("I can handle the cancellation here.")
async def main():
task = asyncio.create_task(sleep())
web_ui_task = asyncio.create_task(web_ui())
await asyncio.wait([web_ui_task, task], return_when=asyncio.FIRST_COMPLETED)
if __name__ == "__main__":
asyncio.run(main())
print("It finished!") |
@Kludex Even when adding such code to manually handle the exit, the exit code is wrong for any naive handling. The program shown exits with That needs quite some extra scaffolding to do right. |
I'm trying to assess the issue.
With the above, the
What is the issue you are trying to solve? I mean real case scenario. |
Hey @Kludex — a use case I have is to run an API server temporarily. For example, to facilitate a browser-based login experience:
Right now, there are a lot of problems with using Uvicorn for a feature like this:
Does that make sense? I definitely could be doing it wrong, but it feels like the
|
This is not sufficient for an
I'm not sure what kind of answer you are expecting to this. "run In our specific case, we use |
Hi all, To chime in with another example. I have a fairly trivial application where in a websocket handler, I'm using an async queue to push messages to clients. On shutdown, I'm using an event and a |
I don't know if this could help but this is my workaround for my use case: import signal
from types import FrameType
from fastapi import FastAPI
app = FastAPI()
@app.on_event("startup")
async def startup_event() -> None:
default_sigint_handler = signal.getsignal(signal.SIGINT)
def terminate_now(signum: int, frame: FrameType = None):
# do whatever you need to unblock your own tasks
default_sigint_handler(signum, frame)
signal.signal(signal.SIGINT, terminate_now) |
You can just override install_signal_handlers function:
And then when you catch interrupt elsewhere you can just signal server to stop:
|
Nice!
|
The following snippet cannot be killed with a SIGINT (ctrl+c):
It appears that uvicorn is eating SIGINTs and does not propagate the KeyboardInterrupt and/or Cancelled exceptions. Thanks for having a look.
Important
The text was updated successfully, but these errors were encountered: