-
-
Notifications
You must be signed in to change notification settings - Fork 702
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
Ctrl+C in terminal broken on windows #1972
Comments
same question |
when you launch without testing properly that will happen, also same here, in addition to that issue with "--reload" parameter over time it stucks and doesn't update api endpoints |
Also the issue of the everything being frozen is generally triggered right after watchfiles tries restarting the server/detected a change, also killing the process manually using the port number doesn't fully terminate it and does not allow for the port to be reused without a full system reboot. |
Crude monkey-patching hack to use import sys
if __name__ == "__main__":
if sys.platform == "win32":
# Based on Eryk Sun's code: https://stackoverflow.com/a/43095532
import ctypes
from signal import SIGINT, CTRL_C_EVENT
_console_ctrl_handlers = {} # must be global / kept alive to avoid GC
kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
PHANDLER_ROUTINE = ctypes.WINFUNCTYPE(
ctypes.wintypes.BOOL,
ctypes.wintypes.DWORD)
def _errcheck_bool(result, func, args):
if not result:
raise ctypes.WinError(ctypes.get_last_error())
return args
kernel32.SetConsoleCtrlHandler.errcheck = _errcheck_bool
kernel32.SetConsoleCtrlHandler.argtypes = (
PHANDLER_ROUTINE,
ctypes.wintypes.BOOL)
from uvicorn.supervisors.multiprocess import Multiprocess
uvicorn_multiprocess_startup_orig = Multiprocess.startup
def uvicorn_multiprocess_startup(self, *args, **kwargs):
ret = uvicorn_multiprocess_startup_orig(self, *args, **kwargs)
def win_ctrl_handler(dwCtrlType):
if (dwCtrlType == CTRL_C_EVENT and
not self.should_exit.is_set()):
kernel32.SetConsoleCtrlHandler(_console_ctrl_handlers[win_ctrl_handler], False)
self.signal_handler(SIGINT, None)
del _console_ctrl_handlers[win_ctrl_handler]
return True
return False
if win_ctrl_handler not in _console_ctrl_handlers:
h = PHANDLER_ROUTINE(win_ctrl_handler)
kernel32.SetConsoleCtrlHandler(h, True)
_console_ctrl_handlers[win_ctrl_handler] = h
return ret
Multiprocess.startup = uvicorn_multiprocess_startup
uvicorn.run("app", workers=4) |
The current workaround which works for this is to run This ensures that the port is freed and also terminates the program correctly. if __name__ == '__main__':
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) |
Does not works for me @AshminJayson .
Sample:
|
@humrochagf , tested, nothing changes, but thanks to your PR I nailed down the problem. I'm on latests Windows 11 23H2 builtin Poweshell, VSCode 1.83.1, Python 3.12.0 (tags/v3.12.0:0fb18b0). The signal is indeed received (CTRL+C), since the shutdown starts, both in 0.23.2 and your #2059 . However, the shutdown process hangs forever, giving the impression of not working, you only see: It does not matter if you pass or not the I found that the server.wait_closed() never returns (or timeouts after minutes): I guess the socket.close() is never closed until timeout?: Line 270 in 732cef6
My dirty workaround:
I also saw Python has an open asyncio.Server.wait_closed() appears to hang indefinitely in 3.12.0a7 but I didn't check how it is related to the So you can merge #2059 but won't solve the(my) problem. It is reproducible even with this from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"} |
Alright, thanks for taking a look at it, I'll run some tests in python 3.12 to see if I can reproduce it 🙂 |
There's a discussion on this issue here, along with a proposed fix: #2122 |
By the way, I'm having the same problem for a while, on Windows 10, both Python 3.9 and 3.11. Don't remember the version I was using with 3.9, but with 3.11 is 0.24.0.post1. Downgrading to 0.21.1 seems to improve the reload behavior, but CTRL+C still doesn't work, with or without reload. By the way, this is somewhat intermittent. It's broken most of the time, but sometimes it just works normally, just often enough to make me doubt my sanity, competence, and the nature of reality itself. |
Not entirely sure if this is the same issue but on Windows 10 I'm also having issues since a python 3.12 upgrade with the NiceGUI framework(that uses uvicorn under the hood for filewatching/serving). Any time I edit & save a file while uvicorn is running, it seems to shut down some process and not properly pick up on file changes plus it's impossible to Ctrl+C out of the application unless I close the browser tab. Python 3.11.x works fine, Python 3.12+ seems to break the filewatcher(unsure if the actual bug is in Uvicorn or in the asyncio/python 3.12/Windows combo). |
I've been using this project for on Windows for quite a while and finally decided to spend some time tonight to look into why this annoying issue is happening. There has been some great discussions over possible fixes to this issue, but it seems like it comes down to the parent process, Why is it the case? The Server subprocesses is able to receive the signals fine. Seems to be an open bug with CPython @humrochagf seems to be on the right path with #2059 by changing the behavior to use a timeout to unblock the parent process and have it receive all the handled signals. Seems to be buggy still though. The fix I've done was replacing the def run(self) -> None:
self.startup()
while not self.should_exit.is_set():
time.sleep(.1)
self.shutdown() Seems to work with my build:
I'm sure it'll work for older versions. |
Hello, now that we have #2183 landing on version 0.30.0 the new process manager seems to solve this issue. If anyone that was also facing this issue is able to check with this version I guess we are good to close this one 🙂 |
Same issue still happening for me on v0.30.1 |
Hello, I just tried with version 0.30.1 and i confirm that the issue is still happening, it is not fixed |
Is this dependent on the OS version or shell/terminal used, perhaps? That would explain why it works for some people but not for others. |
@maxfischer2781 i provide some additional information about OS and shell, that are changed a bit since the first post i made due to some Windows updates, but are pretty similar. Today i tried with these versions: If i downgrade to Uvicorn version 0.21.1 everything works fine, but every version i tried after the 0.21.1 always had the issue |
Encountered the same issue on Win10 with uvicorn It seems this bug is pretty rare and maybe happens only if something specific in code changes? Or even env files, can't be sure. My command: ENV_FILE := $(PWD)/.local.env
.PHONY: main
main:
uvicorn project.app:create_app --factory --reload --port=8100 --env-file=$(ENV_FILE) PS: using |
The same problem with uvicorn 0.30.1 on Win10. The frequency of the is alarming. I just reopened IDE and everything work fine. |
My Linux get a similar problem , when Crtl+C in the envirenment with py:12.4 and uvi:0.30.1, it raise a "KeyboardInterrupt()" ; but when I back to the env with py:12.0 and uvi:0.23.2 , the Ctrl+C shutdown gracefully without any raise. |
With last release of Uvicorn 0.22.0 doing CTRL+C in a windows terminal doesn't work anymore.
Everything is frozen and it is impossible to stop it. In addition the command --reload is broken too, because it doesn't restart anymore, probably because of the same issue.
Tried on Windows 11 and Powershell 7.3.4.
Downgrading to version 0.21.1 makes it works again.
Important
The text was updated successfully, but these errors were encountered: