aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Herrmann <adrian.herrmann@qt.io>2024-03-14 17:43:36 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-03-15 12:43:57 +0000
commit14eb86de63e7cfeabcde49c680bc87441c21c0cc (patch)
tree0073c1953c27af8e83face45b0778c1b1a6f95c5
parent56d52e128a3aa23605889fee3e18b64b80cd9639 (diff)
QtAsyncio: Improve handling of outside termination
Improve how QtAsyncio handles when the QCoreApplication is quit from outside, e.g., when pressing the close button. This will prevent scenarios where asyncio runs the BaseEventLoop destructor after the Qt application had already been shut down, resulting in RuntimeError. In addition, this removes some unnecessary RuntimeError raises related to a closed event loop. Task-number: PYSIDE-769 Change-Id: I52553eed271b5fb5790c09751dd58cc2e52fa174 Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io> (cherry picked from commit 68357b668744be4437527cdf3818b08cee5770c8) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--sources/pyside6/PySide6/QtAsyncio/events.py13
1 files changed, 5 insertions, 8 deletions
diff --git a/sources/pyside6/PySide6/QtAsyncio/events.py b/sources/pyside6/PySide6/QtAsyncio/events.py
index bd58d7dba..cec26ee72 100644
--- a/sources/pyside6/PySide6/QtAsyncio/events.py
+++ b/sources/pyside6/PySide6/QtAsyncio/events.py
@@ -76,7 +76,7 @@ class QAsyncioEventLoopPolicy(asyncio.AbstractEventLoopPolicy):
def get_event_loop(self) -> asyncio.AbstractEventLoop:
if self._event_loop is None:
- self._event_loop = QAsyncioEventLoop(self._application)
+ self._event_loop = QAsyncioEventLoop(self._application, quit_qapp=self._quit_qapp)
return self._event_loop
def set_event_loop(self, loop: typing.Optional[asyncio.AbstractEventLoop]) -> None:
@@ -190,6 +190,7 @@ class QAsyncioEventLoop(asyncio.BaseEventLoop, QObject):
def _about_to_quit_cb(self):
if not self._quit_from_inside:
self._quit_from_outside = True
+ self.close()
def stop(self) -> None:
if self._future_to_complete is not None:
@@ -208,14 +209,12 @@ class QAsyncioEventLoop(asyncio.BaseEventLoop, QObject):
return self._closed
def close(self) -> None:
- if self.is_running():
+ if self.is_running() and not self._quit_from_outside:
raise RuntimeError("Cannot close a running event loop")
if self.is_closed():
return
if self._default_executor is not None:
self._default_executor.shutdown(wait=False)
- if self._quit_qapp:
- self._application.shutdown()
self._closed = True
async def shutdown_asyncgens(self) -> None:
@@ -275,6 +274,8 @@ class QAsyncioEventLoop(asyncio.BaseEventLoop, QObject):
def call_soon_threadsafe(self, callback: typing.Callable, *args: typing.Any,
context:
typing.Optional[contextvars.Context] = None) -> asyncio.Handle:
+ if self.is_closed():
+ raise RuntimeError("Event loop is closed")
if context is None:
context = contextvars.copy_context()
return self._call_soon_impl(callback, *args, context=context, is_threadsafe=True)
@@ -299,8 +300,6 @@ class QAsyncioEventLoop(asyncio.BaseEventLoop, QObject):
is_threadsafe: typing.Optional[bool] = False) -> asyncio.TimerHandle:
if not isinstance(when, (int, float)):
raise TypeError("when must be an int or float")
- if self.is_closed():
- raise RuntimeError("Event loop is closed")
return QAsyncioTimerHandle(when, callback, args, self, context, is_threadsafe=is_threadsafe)
def call_at(self, when: typing.Union[int, float],
@@ -320,8 +319,6 @@ class QAsyncioEventLoop(asyncio.BaseEventLoop, QObject):
coro: typing.Union[collections.abc.Generator, collections.abc.Coroutine],
*, name: typing.Optional[str] = None,
context: typing.Optional[contextvars.Context] = None) -> tasks.QAsyncioTask:
- if self.is_closed():
- raise RuntimeError("Event loop is closed")
if self._task_factory is None:
task = tasks.QAsyncioTask(coro, loop=self, name=name, context=context)
else: