diff --git a/sanic/app.py b/sanic/app.py index e32f0b7659..5c4e7b8f35 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -1878,7 +1878,10 @@ def purge_tasks(self) -> None: } def shutdown_tasks( - self, timeout: float | None = None, increment: float = 0.1 + self, + timeout: float | None = None, + increment: float = 0.1, + loop: asyncio.AbstractEventLoop | None = None, ) -> None: """Cancel all tasks except the server task. @@ -1893,6 +1896,8 @@ def shutdown_tasks( to complete. Defaults to `None`. increment (float): The amount of time to wait between checks for whether the tasks have completed. Defaults to `0.1`. + loop (Optional[asyncio.AbstractEventLoop]): The event loop to use + for waiting. If not provided, attempts to get the running loop. """ for task in self.tasks: if task.get_name() != "RunServer": @@ -1901,10 +1906,17 @@ def shutdown_tasks( if timeout is None: timeout = self.config.GRACEFUL_SHUTDOWN_TIMEOUT - while len(self._task_registry) and timeout: - with suppress(RuntimeError): - running_loop = get_running_loop() - running_loop.run_until_complete(asyncio.sleep(increment)) + if loop is None: + try: + loop = get_running_loop() + except RuntimeError: + loop = asyncio.get_event_loop_policy().get_event_loop() + + while self._task_registry and timeout > 0: + try: + loop.run_until_complete(asyncio.sleep(increment)) + except RuntimeError: + pass self.purge_tasks() timeout -= increment diff --git a/sanic/server/runners.py b/sanic/server/runners.py index 9543ac81ba..23f77e634c 100644 --- a/sanic/server/runners.py +++ b/sanic/server/runners.py @@ -322,7 +322,7 @@ def _cleanup(): loop.run_until_complete(asyncio.sleep(0.1)) start_shutdown = start_shutdown + 0.1 - app.shutdown_tasks(graceful - start_shutdown) + app.shutdown_tasks(graceful - start_shutdown, loop=loop) # Force close non-idle connection after waiting for # graceful_shutdown_timeout