Skip to content

Commit

Permalink
Fix shutdown event on Windows in reloader (#1584)
Browse files Browse the repository at this point in the history
Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com>
  • Loading branch information
StarHeartHunt and Kludex committed Apr 13, 2023
1 parent 23deb2b commit b934b3d
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 4 deletions.
1 change: 1 addition & 0 deletions setup.cfg
Expand Up @@ -47,6 +47,7 @@ exclude_lines =
[coverage:coverage_conditional_plugin]
rules =
"sys_platform == 'win32'": py-win32
"sys_platform != 'win32'": py-not-win32
"sys_platform == 'linux'": py-linux
"sys_platform == 'darwin'": py-darwin
"sys_version_info >= (3, 8)": py-gte-38
Expand Down
6 changes: 5 additions & 1 deletion tests/supervisors/test_reload.py
@@ -1,6 +1,7 @@
import logging
import signal
import socket
import sys
from pathlib import Path
from time import sleep
from typing import Optional, Type
Expand Down Expand Up @@ -393,7 +394,10 @@ def test_base_reloader_should_exit(tmp_path):
assert not reloader.should_exit.is_set()
reloader.pause()

reloader.signal_handler(signal.SIGINT, None)
if sys.platform == "win32":
reloader.signal_handler(signal.CTRL_C_EVENT, None) # pragma: py-not-win32
else:
reloader.signal_handler(signal.SIGINT, None) # pragma: py-win32

assert reloader.should_exit.is_set()
with pytest.raises(StopIteration):
Expand Down
19 changes: 16 additions & 3 deletions uvicorn/supervisors/basereload.py
@@ -1,6 +1,7 @@
import logging
import os
import signal
import sys
import threading
from pathlib import Path
from socket import socket
Expand Down Expand Up @@ -32,13 +33,17 @@ def __init__(
self.sockets = sockets
self.should_exit = threading.Event()
self.pid = os.getpid()
self.is_restarting = False
self.reloader_name: Optional[str] = None

def signal_handler(self, sig: int, frame: Optional[FrameType]) -> None:
"""
A signal handler that is registered with the parent process.
"""
self.should_exit.set()
if sys.platform == "win32" and self.is_restarting:
self.is_restarting = False # pragma: py-not-win32
else:
self.should_exit.set() # pragma: py-win32

def run(self) -> None:
self.startup()
Expand Down Expand Up @@ -80,7 +85,12 @@ def startup(self) -> None:
self.process.start()

def restart(self) -> None:
self.process.terminate()
if sys.platform == "win32": # pragma: py-not-win32
self.is_restarting = True
assert self.process.pid is not None
os.kill(self.process.pid, signal.CTRL_C_EVENT)
else: # pragma: py-win32
self.process.terminate()
self.process.join()

self.process = get_subprocess(
Expand All @@ -89,7 +99,10 @@ def restart(self) -> None:
self.process.start()

def shutdown(self) -> None:
self.process.terminate()
if sys.platform == "win32":
self.should_exit.set() # pragma: py-not-win32
else:
self.process.terminate() # pragma: py-win32
self.process.join()

for sock in self.sockets:
Expand Down

0 comments on commit b934b3d

Please sign in to comment.