From a1caa930544f9ba542c236028fdc698f5d018b4f Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Mon, 4 Jul 2016 13:22:35 +1000 Subject: [PATCH] fix mem leaks in dialogs - ensure we're cleaning them up after they're rejected - run the garbage collector afterwards so the qwebengineprocess instances get cleaned up --- aqt/about.py | 5 +++-- aqt/addcards.py | 1 + aqt/browser.py | 2 ++ aqt/clayout.py | 1 + aqt/main.py | 21 +++++++++++++++++++++ aqt/stats.py | 1 + 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/aqt/about.py b/aqt/about.py index 6875c9d07..1a473f8c7 100644 --- a/aqt/about.py +++ b/aqt/about.py @@ -7,8 +7,9 @@ import aqt.forms from aqt import appVersion from aqt.utils import openLink -def show(parent): - dialog = QDialog(parent) +def show(mw): + dialog = QDialog(mw) + mw.setupDialogGC(dialog) abt = aqt.forms.about.Ui_About() abt.setupUi(dialog) abouttext = "
" diff --git a/aqt/addcards.py b/aqt/addcards.py index 4effd4b98..40b3a66b4 100644 --- a/aqt/addcards.py +++ b/aqt/addcards.py @@ -16,6 +16,7 @@ class AddCards(QDialog): def __init__(self, mw): QDialog.__init__(self, None, Qt.Window) + mw.setupDialogGC(self) self.mw = mw self.form = aqt.forms.addcards.Ui_Dialog() self.form.setupUi(self) diff --git a/aqt/browser.py b/aqt/browser.py index 2c8e4cfbb..618db5159 100644 --- a/aqt/browser.py +++ b/aqt/browser.py @@ -466,6 +466,7 @@ class Browser(QMainWindow): aqt.dialogs.close("Browser") self.teardownHooks() self.mw.maybeReset() + self.mw.gcWindow(self) evt.accept() def canClose(self): @@ -1375,6 +1376,7 @@ update cards set usn=?, mod=?, did=? where id in """ + scids, def onFindDupes(self): d = QDialog(self) + self.mw.setupDialogGC(d) frm = aqt.forms.finddupes.Ui_Dialog() frm.setupUi(d) restoreGeom(d, "findDupes") diff --git a/aqt/clayout.py b/aqt/clayout.py index 033c37126..864b04145 100644 --- a/aqt/clayout.py +++ b/aqt/clayout.py @@ -20,6 +20,7 @@ class CardLayout(QDialog): def __init__(self, mw, note, ord=0, parent=None, addMode=False): QDialog.__init__(self, parent or mw, Qt.Window) + mw.setupDialogGC(self) self.mw = aqt.mw self.parent = parent or mw self.note = note diff --git a/aqt/main.py b/aqt/main.py index 25169ac95..e64cc3673 100644 --- a/aqt/main.py +++ b/aqt/main.py @@ -5,6 +5,8 @@ import re import signal import zipfile +import gc +import time from send2trash import send2trash from aqt.qt import * @@ -1139,3 +1141,22 @@ Please ensure a profile is open and Anki is not busy, then try again."""), return # import self.handleImport(buf) + + # GC + ########################################################################## + # run the garbage collector after object is deleted so we don't leave + # expensive web engine processes lying around + + def setupDialogGC(self, obj): + obj.finished.connect(lambda o=obj: self.gcWindow(obj)) + + def gcWindow(self, obj): + obj.deleteLater() + t = QTimer(self) + t.timeout.connect(self._onCollect) + t.setSingleShot(True) + # will run next time queue is idle + t.start(0) + + def _onCollect(self): + gc.collect() diff --git a/aqt/stats.py b/aqt/stats.py index 7ef4419e7..7bd252672 100644 --- a/aqt/stats.py +++ b/aqt/stats.py @@ -14,6 +14,7 @@ class DeckStats(QDialog): def __init__(self, mw): QDialog.__init__(self, mw, Qt.Window) + mw.setupDialogGC(self) self.mw = mw self.name = "deckStats" self.period = 0