From cc97287f8eea5bf8d5c3af42586f1e802035439b Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Sun, 17 Apr 2022 05:25:41 -0400 Subject: [PATCH] Add fall back for Windows even loop fetching (#2421) --- sanic/__version__.py | 2 +- sanic/app.py | 8 +++++++- sanic/compat.py | 2 +- tests/test_signal_handlers.py | 12 +++++++----- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/sanic/__version__.py b/sanic/__version__.py index 847ff8e6..667ec2f0 100644 --- a/sanic/__version__.py +++ b/sanic/__version__.py @@ -1 +1 @@ -__version__ = "22.3.0" +__version__ = "22.3.1" diff --git a/sanic/app.py b/sanic/app.py index a67b437d..4dbb1b2e 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -252,7 +252,13 @@ class Sanic(BaseSanic, RunnerMixin, metaclass=TouchUpMeta): "Loop can only be retrieved after the app has started " "running. Not supported with `create_server` function" ) - return get_running_loop() + try: + return get_running_loop() + except RuntimeError: + if sys.version_info > (3, 10): + return asyncio.get_event_loop_policy().get_event_loop() + else: + return asyncio.get_event_loop() # -------------------------------------------------------------------- # # Registration diff --git a/sanic/compat.py b/sanic/compat.py index e28e64a1..d8e0bea1 100644 --- a/sanic/compat.py +++ b/sanic/compat.py @@ -72,7 +72,7 @@ def ctrlc_workaround_for_windows(app): """Asyncio wakeups to allow receiving SIGINT in Python""" while not die: # If someone else stopped the app, just exit - if app.is_stopping: + if app.state.is_stopping: return # Windows Python blocks signal handlers while the event loop is # waiting for I/O. Frequent wakeups keep interrupts flowing. diff --git a/tests/test_signal_handlers.py b/tests/test_signal_handlers.py index c6838b5e..ee28f548 100644 --- a/tests/test_signal_handlers.py +++ b/tests/test_signal_handlers.py @@ -3,6 +3,7 @@ import os import signal from queue import Queue +from types import SimpleNamespace from unittest.mock import MagicMock import pytest @@ -74,11 +75,12 @@ def test_windows_workaround(): # Windows... class MockApp: def __init__(self): - self.is_stopping = False + self.state = SimpleNamespace() + self.state.is_stopping = False def stop(self): - assert not self.is_stopping - self.is_stopping = True + assert not self.state.is_stopping + self.state.is_stopping = True def add_task(self, func): loop = asyncio.get_event_loop() @@ -91,11 +93,11 @@ def test_windows_workaround(): if stop_first: app.stop() await asyncio.sleep(0.2) - assert app.is_stopping == stop_first + assert app.state.is_stopping == stop_first # First Ctrl+C: should call app.stop() within 0.1 seconds os.kill(os.getpid(), signal.SIGINT) await asyncio.sleep(0.2) - assert app.is_stopping + assert app.state.is_stopping assert app.stay_active_task.result() is None # Second Ctrl+C should raise with pytest.raises(KeyboardInterrupt):