Skip to content

Commit cd49dc6

Browse files
committed
Initialize asyncio event loop before using it
Python 3.14 (in Fedora 43) throws RunetimeError if event loop is not initialized before using it. Resolves: QubesOS/qubes-issues#10188
1 parent 5140b97 commit cd49dc6

13 files changed

Lines changed: 38 additions & 31 deletions

doc/qubes-events.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,7 @@ handler (a coroutine) for synchronous event (the one fired with
177177
178178
o = MyClass()
179179
o.events_enabled = True
180-
loop = asyncio.get_event_loop()
181-
loop.run_until_complete(o.fire_event_async('event1'))
180+
asyncio.run(o.fire_event_async('event1'))
182181
183182
Asynchronous event handlers can also return value - but only a collection, not
184183
yield individual values (because of python limitation):
@@ -207,7 +206,8 @@ yield individual values (because of python limitation):
207206
208207
o = MyClass()
209208
o.events_enabled = True
210-
loop = asyncio.get_event_loop()
209+
loop = asyncio.new_event_loop()
210+
asyncio.set_event_loop(loop)
211211
# returns ['sync result', 'result1', 'result2', 'result3', 'result4'],
212212
# possibly not in order
213213
effects = loop.run_until_complete(o.fire_event_async('event1'))

qubes/backup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ class Backup:
256256
>>> }
257257
>>> backup_op = Backup(app, vms, exclude_vms, **options)
258258
>>> print(backup_op.get_backup_summary())
259-
>>> asyncio.get_event_loop().run_until_complete(backup_op.backup_do())
259+
>>> asyncio.run(backup_op.backup_do())
260260
261261
See attributes of this object for all available options.
262262

qubes/tests/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,8 @@ def setUp(self):
513513
super().setUp()
514514
self.addCleanup(self.cleanup_gc)
515515

516-
self.loop = asyncio.get_event_loop()
516+
self.loop = asyncio.new_event_loop()
517+
asyncio.set_event_loop(self.loop)
517518
self.addCleanup(self.cleanup_loop)
518519

519520
self.kernel_validator_original = qubes.app.validate_kernel

qubes/tests/api_admin.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ def call_mgmt_func(self, method, dest, arg=b"", payload=b""):
145145
self.app, b"dom0", method, dest, arg
146146
)
147147

148-
loop = asyncio.get_event_loop()
148+
loop = asyncio.new_event_loop()
149+
asyncio.set_event_loop(loop)
149150
response = loop.run_until_complete(
150151
mgmt_obj.execute(untrusted_payload=payload)
151152
)
@@ -158,7 +159,8 @@ def call_internal_mgmt_func(self, method, dest, arg=b"", payload=b""):
158159
mgmt_obj = qubes.api.internal.QubesInternalAPI(
159160
self.app, b"dom0", method, dest, arg
160161
)
161-
loop = asyncio.get_event_loop()
162+
loop = asyncio.new_event_loop()
163+
asyncio.set_event_loop(loop)
162164
response = loop.run_until_complete(
163165
mgmt_obj.execute(untrusted_payload=payload)
164166
)
@@ -230,7 +232,8 @@ def test_002_vm_list_filter(self):
230232
mgmt_obj = qubes.api.admin.QubesAdminAPI(
231233
self.app, b"test-vm1", b"admin.vm.List", b"dom0", b""
232234
)
233-
loop = asyncio.get_event_loop()
235+
loop = asyncio.new_event_loop()
236+
asyncio.set_event_loop(loop)
234237
value = loop.run_until_complete(
235238
mgmt_obj.execute(untrusted_payload=b"")
236239
)
@@ -3762,7 +3765,8 @@ def __init__(self, name):
37623765
def name(self):
37633766
return self._name
37643767

3765-
loop = asyncio.get_event_loop()
3768+
loop = asyncio.new_event_loop()
3769+
asyncio.set_event_loop(loop)
37663770
self.app.vmm.libvirt_conn.lookupByID.side_effect = lambda xid: {
37673771
0: MockVM("Domain-0"),
37683772
1: MockVM("test-template"),
@@ -3862,7 +3866,8 @@ def __init__(self, name):
38623866
def name(self):
38633867
return self._name
38643868

3865-
loop = asyncio.get_event_loop()
3869+
loop = asyncio.new_event_loop()
3870+
asyncio.set_event_loop(loop)
38663871
self.app.vmm.libvirt_conn.lookupByID.side_effect = lambda xid: {
38673872
0: MockVM("Domain-0"),
38683873
1: MockVM("test-template"),

qubes/tests/api_internal.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ def call_mgmt_func(self, method, arg=b"", payload=b""):
7979
self.app, b"dom0", method, b"dom0", arg
8080
)
8181

82-
loop = asyncio.get_event_loop()
82+
loop = asyncio.new_event_loop()
83+
asyncio.set_event_loop(loop)
8384
response = loop.run_until_complete(
8485
mgmt_obj.execute(untrusted_payload=payload)
8586
)

qubes/tests/api_misc.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ def call_mgmt_func(self, method, arg=b"", payload=b""):
6363
self.app, b"test-vm", method, b"dom0", arg
6464
)
6565

66-
loop = asyncio.get_event_loop()
66+
loop = asyncio.new_event_loop()
67+
asyncio.set_event_loop(loop)
6768
response = loop.run_until_complete(
6869
mgmt_obj.execute(untrusted_payload=payload)
6970
)

qubes/tests/devices_block.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ def async_test(f):
3939
def wrapper(*args, **kwargs):
4040
coro = asyncio.coroutine(f)
4141
future = coro(*args, **kwargs)
42-
loop = asyncio.get_event_loop()
42+
loop = asyncio.new_event_loop()
43+
asyncio.set_event_loop(loop)
4344
loop.run_until_complete(future)
4445

4546
return wrapper
@@ -1124,9 +1125,8 @@ def test_071_failed_confirmation(self, socket):
11241125

11251126
socket.return_value = "allow:nonsense"
11261127

1127-
loop = asyncio.get_event_loop()
11281128
self.ext.attach_and_notify = AsyncMock()
1129-
loop.run_until_complete(
1129+
asyncio.run(
11301130
qubes.ext.utils.resolve_conflicts_and_attach(
11311131
self.ext, {"sda": {front: assign, back: assign}}
11321132
)
@@ -1149,9 +1149,8 @@ def test_072_successful_confirmation(self, socket):
11491149

11501150
socket.return_value = "allow:front-vm"
11511151

1152-
loop = asyncio.get_event_loop()
11531152
self.ext.attach_and_notify = AsyncMock()
1154-
loop.run_until_complete(
1153+
asyncio.run(
11551154
qubes.ext.utils.resolve_conflicts_and_attach(
11561155
self.ext, {"sda": {front: assign, back: assign}}
11571156
)
@@ -1203,10 +1202,9 @@ def test_080_on_startup_multiple_assignments_including_full(self):
12031202
)
12041203

12051204
self.ext.attach_and_notify = Mock()
1206-
loop = asyncio.get_event_loop()
12071205
with mock.patch("asyncio.wait"):
12081206
with mock.patch("asyncio.ensure_future"):
1209-
loop.run_until_complete(self.ext.on_domain_start(front, None))
1207+
asyncio.run(self.ext.on_domain_start(front, None))
12101208
self.assertEqual(
12111209
self.ext.attach_and_notify.call_args[0][1].options, {"pid": "did"}
12121210
)
@@ -1235,10 +1233,9 @@ def test_081_on_startup_multiple_assignments_port_vs_dev(self):
12351233
)
12361234

12371235
self.ext.attach_and_notify = Mock()
1238-
loop = asyncio.get_event_loop()
12391236
with mock.patch("asyncio.wait"):
12401237
with mock.patch("asyncio.ensure_future"):
1241-
loop.run_until_complete(self.ext.on_domain_start(front, None))
1238+
asyncio.run(self.ext.on_domain_start(front, None))
12421239
self.assertEqual(
12431240
self.ext.attach_and_notify.call_args[0][1].options, {"pid": "any"}
12441241
)
@@ -1270,10 +1267,9 @@ def test_082_on_startup_multiple_assignments_dev(self):
12701267
)
12711268

12721269
self.ext.attach_and_notify = Mock()
1273-
loop = asyncio.get_event_loop()
12741270
with mock.patch("asyncio.wait"):
12751271
with mock.patch("asyncio.ensure_future"):
1276-
loop.run_until_complete(self.ext.on_domain_start(front, None))
1272+
asyncio.run(self.ext.on_domain_start(front, None))
12771273
self.assertEqual(
12781274
self.ext.attach_and_notify.call_args[0][1].options, {"any": "did"}
12791275
)
@@ -1299,7 +1295,6 @@ def test_083_on_startup_already_attached(self):
12991295
back.devices["block"]._exposed.append(exp_dev)
13001296

13011297
self.ext.attach_and_notify = Mock()
1302-
loop = asyncio.get_event_loop()
13031298
with mock.patch("asyncio.ensure_future"):
1304-
loop.run_until_complete(self.ext.on_domain_start(front, None))
1299+
asyncio.run(self.ext.on_domain_start(front, None))
13051300
self.ext.attach_and_notify.assert_not_called()

qubes/tests/events.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ async def on_testevent_3(self, event):
151151
def on_testevent_4(self, event):
152152
return ("testvalue4",)
153153

154-
loop = asyncio.get_event_loop()
154+
loop = asyncio.new_event_loop()
155+
asyncio.set_event_loop(loop)
155156
emitter = TestEmitter()
156157
emitter.events_enabled = True
157158

qubes/tests/integ/backupcompatibility.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ def assertRestored(self, name, **kwargs):
473473

474474
with self.assertNotRaises((KeyError, qubes.exc.QubesException)):
475475
vm = self.app.domains[name]
476-
asyncio.get_event_loop().run_until_complete(vm.storage.verify())
476+
asyncio.run(vm.storage.verify())
477477
for prop, value in kwargs.items():
478478
if prop == "klass":
479479
self.assertIsInstance(vm, value)

qubes/tools/qubes_create.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def main(args=None):
4040
"""
4141

4242
args = parser.parse_args(args)
43-
asyncio.get_event_loop().run_until_complete(
43+
asyncio.run(
4444
qubes.Qubes.create_empty_store(
4545
args.app, offline_mode=args.offline_mode
4646
).setup_pools()

0 commit comments

Comments
 (0)