Skip to content

Commit 6778769

Browse files
committed
Clean up stopped event loop, disconnecting signals and file descriptor notifiers
1 parent 24aac32 commit 6778769

2 files changed

Lines changed: 38 additions & 9 deletions

File tree

qasync/__init__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,9 @@ def __init__(self, app=None, set_running_loop=False, already_running=False):
342342

343343
self.__call_soon_signaller = signaller = _make_signaller(QtCore, object, tuple)
344344
self.__call_soon_signal = signaller.signal
345-
signaller.signal.connect(lambda callback, args: self.call_soon(callback, *args))
345+
self.__call_soon_signal.connect(
346+
lambda callback, args: self.call_soon(callback, *args)
347+
)
346348

347349
assert self.__app is not None
348350
super().__init__()
@@ -438,6 +440,9 @@ def close(self):
438440
if self.__default_executor is not None:
439441
self.__default_executor.shutdown()
440442

443+
if self.__call_soon_signal:
444+
self.__call_soon_signal.disconnect()
445+
441446
super().close()
442447

443448
self._timer.stop()
@@ -524,6 +529,7 @@ def _remove_reader(self, fd):
524529
return False
525530
else:
526531
notifier.setEnabled(False)
532+
notifier.activated["int"].disconnect()
527533
return True
528534

529535
def _add_writer(self, fd, callback, *args):
@@ -564,6 +570,7 @@ def _remove_writer(self, fd):
564570
return False
565571
else:
566572
notifier.setEnabled(False)
573+
notifier.activated["int"].disconnect()
567574
return True
568575

569576
def __notifier_cb_wrapper(self, notifiers, notifier, fd, callback, args):
@@ -579,8 +586,6 @@ def __notifier_cb_wrapper(self, notifiers, notifier, fd, callback, args):
579586
# callback. We must not re-enable it in that case.
580587
if notifiers.get(fd, None) is notifier:
581588
notifier.setEnabled(True)
582-
else:
583-
notifier.activated["int"].disconnect()
584589

585590
def __on_notifier_ready(self, notifiers, notifier, fd, callback, args):
586591
if fd not in notifiers:

tests/test_qeventloop.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44
# BSD License
55

66
import asyncio
7-
import logging
8-
import sys
9-
import os
107
import ctypes
8+
import gc
9+
import logging
1110
import multiprocessing
12-
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
11+
import os
1312
import socket
1413
import subprocess
15-
16-
import qasync
14+
import sys
15+
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
1716

1817
import pytest
1918

19+
import qasync
20+
2021

2122
@pytest.fixture
2223
def loop(request, application):
@@ -790,6 +791,29 @@ async def mycoro():
790791
assert not loop.is_running()
791792

792793

794+
def test_selector_event_loop_cleanup(application):
795+
gc.collect()
796+
797+
async def app_main():
798+
pass
799+
800+
def run_app(app):
801+
event_loop = qasync.QEventLoop(app)
802+
event_loop.run_until_complete(app_main())
803+
event_loop.close()
804+
805+
for _ in range(5):
806+
run_app(application)
807+
gc.collect()
808+
loops = [
809+
obj
810+
for obj in gc.get_objects()
811+
if type(obj).__name__ == "QSelectorEventLoop"
812+
]
813+
assert len(loops) == 0
814+
del loops
815+
816+
793817
def teardown_module(module):
794818
"""
795819
Remove handlers from all loggers

0 commit comments

Comments
 (0)