]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
python: backport 'Remove deprecated get_event_loop calls'
authorJohn Snow <jsnow@redhat.com>
Tue, 13 Aug 2024 13:35:30 +0000 (09:35 -0400)
committerJohn Snow <jsnow@redhat.com>
Mon, 15 Sep 2025 18:36:01 +0000 (14:36 -0400)
This method was deprecated in 3.12 because it ordinarily should not be
used from coroutines; if there is not a currently running event loop,
this automatically creates a new event loop - which is usually not what
you want from code that would ever run in the bottom half.

In our case, we do want this behavior in two places:

(1) The synchronous shim, for convenience: this allows fully sync
programs to use QEMUMonitorProtocol() without needing to set up an event
loop beforehand. This is intentional to fully box in the async
complexities into the legacy sync shim.

(2) The qmp_tui shell; instead of relying on asyncio.run to create and
run an asyncio program, we need to be able to pass the current asyncio
loop to urwid setup functions. For convenience, again, we create one if
one is not present to simplify the creation of the TUI appliance.

The remaining user of get_event_loop() was in fact one of the erroneous
users that should not have been using this function: if there's no
running event loop inside of a coroutine, you're in big trouble :)

Signed-off-by: John Snow <jsnow@redhat.com>
cherry picked from commit python-qemu-qmp@aa1ff9907603a3033296027e1bd021133df86ef1
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
python/qemu/qmp/legacy.py
python/qemu/qmp/qmp_tui.py
python/tests/protocol.py

index c8d0a29b56fe03bc230befec986595a6402fe38b..735d42971e907513be6cac8fe36ddb503af9e30d 100644 (file)
@@ -86,7 +86,14 @@ class QEMUMonitorProtocol:
                 "server argument should be False when passing a socket")
 
         self._qmp = QMPClient(nickname)
-        self._aloop = asyncio.get_event_loop()
+
+        try:
+            self._aloop = asyncio.get_running_loop()
+        except RuntimeError:
+            # No running loop; since this is a sync shim likely to be
+            # used in fully sync programs, create one if neccessary.
+            self._aloop = asyncio.get_event_loop_policy().get_event_loop()
+
         self._address = address
         self._timeout: Optional[float] = None
 
index 53ea6c59a714f9feadc6fadd151f962e879ece63..12bdc17c99ed7acda8bc2ddebb0b344bdb803e2f 100644 (file)
@@ -388,7 +388,12 @@ class App(QMPClient):
         screen = urwid.raw_display.Screen()
         screen.set_terminal_properties(256)
 
-        self.aloop = asyncio.get_event_loop()
+        try:
+            self.aloop = asyncio.get_running_loop()
+        except RuntimeError:
+            # No running asyncio event loop. Create one if necessary.
+            self.aloop = asyncio.get_event_loop_policy().get_event_loop()
+
         self.aloop.set_debug(debug)
 
         # Gracefully handle SIGTERM and SIGINT signals
index c254c77b176be521c45d6f76b2e3f2071c93c5bf..e565802516d2297f7048cdd10c31cde18ecbe8c5 100644 (file)
@@ -227,7 +227,7 @@ class TestBase(avocado.Test):
         Decorator; adds SetUp and TearDown to async tests.
         """
         async def _wrapper(self, *args, **kwargs):
-            loop = asyncio.get_event_loop()
+            loop = asyncio.get_running_loop()
             loop.set_debug(True)
 
             await self._asyncSetUp()