Hinweis: Ich habe dies auch auf der PyQt-Mailingliste gepostet - ich beantworte meine eigene Frage hier, wenn eine gute Antwort dort kommt.PyQt: gelegentliche segfaults bei Verwendung von QApplication.quit
Ich habe Probleme mit gelegentlichen segfaults haben, wenn QApplication.quit()
ausgeführt wird, möglicherweise im Zusammenhang mit libQt5Network.so und/oder QtWebKit.
Vor allem die drei Testsysteme Ich verwende:
- Arch Linux, PyQt 5.2, Qt 5.2.0, Python 3.3.3
- Ubuntu 13.10, PyQt 5.0.1, Qt 5.0.2, Python 3.3.2 in einem VM
- Windows 7, PyQt 5.2, Qt 5.2.0, Python 3.3.3
Diese Abstürze nie so weit für mich auf Arch passiert ist, sehr oft auf Ubuntu und von Zeit zu Zeit in Windows. (Obwohl Windows ist nur eine Vermutung , bekomme ich nur diese python.exe nicht funktioniert mehr foo.)
Original-Absturz
ich zum ersten Mal das Problem in einem großen (ger) Projekt bemerkt, qutebrowser, wo es mir diese stacktrace gab, als :quit
(auf Ubuntu) eingeben:
#0 0xb5c296fc in QMutex::lock()() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#1 0xb3bdd97d in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#2 0xb3bdf0d0 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#3 0xb3bd4418 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#4 0xb3bd8b1e in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#5 0xb5dedf10 in QMetaObject::activate(QObject*, int, int, void**)()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#6 0xb5dee48b in QMetaObject::activate(QObject*, QMetaObject const*, int, void**)() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#7 0xb5e59155 in QIODevice::readyRead()()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#8 0xb3bb1f14 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#9 0xb3ba4d99 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#10 0xb3bc03bb in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#11 0xb6483a54 in QApplicationPrivate::notify_helper(QObject*, QEvent*)()
from /usr/lib/i386-linux-gnu/libQt5Widgets.so.5
#12 0xb6488e66 in QApplication::notify(QObject*, QEvent*)()
from /usr/lib/i386-linux-gnu/libQt5Widgets.so.5
#13 0xb6bb7e80 in sipQApplication::notify(QObject*, QEvent*)()
from /usr/lib/python3/dist-packages/PyQt5/QtWidgets.cpython-33m-i386-linux-gnu.so
#14 0xb5dc737a in QCoreApplication::notifyInternal(QObject*, QEvent*)()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#15 0xb5e11f67 in ??() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#16 0xb5aaf83e in g_main_context_dispatch()
from /lib/i386-linux-gnu/libglib-2.0.so.0
#17 0xb5aafbe8 in ??() from /lib/i386-linux-gnu/libglib-2.0.so.0
#18 0xb5aafca8 in g_main_context_iteration()
from /lib/i386-linux-gnu/libglib-2.0.so.0
#19 0xb5e1138f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#20 0xb5dc5c06 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#21 0xb5dc6014 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#22 0xb5c2b90b in QThread::exec()()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#23 0xb5c2b99b in QThread::run()() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#24 0xb5c2fa08 in ??() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#25 0xb7774d78 in start_thread (arg=0xa5314b40) at pthread_create.c:311
#26 0xb76ac01e in clone() at ../sysdeps/unix/sysv/linux/i386/clone.S:131
Core dump here (15MB, gzip).
Minimal Beispiel
Dann habe ich versucht wieder mit einem minimalen Beispiel, das sich automatisch nach einer Sekunde mit einer QTimer beendet. Ich hatte es in einer Schleife für etwa eine Minute oder so laufen, bevor es passiert ist:
from PyQt5.QtCore import QUrl, QTimer
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKitWidgets import QWebView
app = QApplication([])
wv = QWebView()
wv.load(QUrl("http://www.heise.de/"))
t = QTimer()
t.timeout.connect(QApplication.quit)
t.start(1000)
wv.show()
app.exec_()
Dies gab mir diese sehr ähnlich stacktrace (auf Ubuntu):
#0 0xb6cfd8d2 in QCoreApplication::postEvent(QObject*, QEvent*, int)()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#1 0xb6d21c83 in QMetaObject::activate(QObject*, int, int, void**)()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#2 0xb6d2248b in QMetaObject::activate(QObject*, QMetaObject const*, int, void**)() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#3 0xb3e47935 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#4 0xb3dcf687 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#5 0xb3e483b3 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#6 0xb6d21f10 in QMetaObject::activate(QObject*, int, int, void**)()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#7 0xb6d2248b in QMetaObject::activate(QObject*, QMetaObject const*, int, void**)() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#8 0xb3e43fe5 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#9 0xb3d93b1e in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#10 0xb3d94630 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#11 0xb3d9471b in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#12 0xb6d21f10 in QMetaObject::activate(QObject*, int, int, void**)()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#13 0xb6d2248b in QMetaObject::activate(QObject*, QMetaObject const*, int, void**)() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#14 0xb6d8d155 in QIODevice::readyRead()()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#15 0xb3e09f14 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#16 0xb3dfcd99 in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#17 0xb3e183bb in ??() from /usr/lib/i386-linux-gnu/libQt5Network.so.5
#18 0xb492ba54 in QApplicationPrivate::notify_helper(QObject*, QEvent*)()
from /usr/lib/i386-linux-gnu/libQt5Widgets.so.5
#19 0xb4930e66 in QApplication::notify(QObject*, QEvent*)()
from /usr/lib/i386-linux-gnu/libQt5Widgets.so.5
#20 0xb505fe80 in sipQApplication::notify(QObject*, QEvent*)()
from /usr/lib/python3/dist-packages/PyQt5/QtWidgets.cpython-33m-i386-linux-gnu.so
#21 0xb6cfb37a in QCoreApplication::notifyInternal(QObject*, QEvent*)()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#22 0xb6d45f67 in ??() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#23 0xb65f483e in g_main_context_dispatch()
from /lib/i386-linux-gnu/libglib-2.0.so.0
#24 0xb65f4be8 in ??() from /lib/i386-linux-gnu/libglib-2.0.so.0
#25 0xb65f4ca8 in g_main_context_iteration()
from /lib/i386-linux-gnu/libglib-2.0.so.0
#26 0xb6d4536d in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#27 0xb6cf9c06 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#28 0xb6cfa014 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#29 0xb6b5f90b in QThread::exec()()
from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#30 0xb6b5f99b in QThread::run()() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#31 0xb6b63a08 in ??() from /usr/lib/i386-linux-gnu/libQt5Core.so.5
#32 0xb7798d78 in start_thread (arg=0xa7812b40) at pthread_create.c:311
#33 0xb76d001e in clone() at ../sysdeps/unix/sysv/linux/i386/clone.S:131
Coredump here (15MB, gzip).
Hat jemand eine Idee, was schief läuft? Irgendeine Magie mit Sachen Müll-gesammelt in die falsche Richtung? Ich versuchte auch einige Workarounds * für ähnliche Symptome auf PyQt4, aber das tat Hilfe entweder nicht.
* kann nicht die Stackoverflow-Antwort finden, wo es beschrieben wurde - grundsätzlich QtWidgets.qApp
auf die QApplication
Instanz vor Einstellung exec_()
ausgeführt wird, und auf None
danach.
Dank! Ihr Tutorial scheint auch für andere zukünftige Probleme nützlich zu sein. Wenn du Zeit hast, könntest du einen Blick darauf werfen, ob meine [Umsetzung davon] (http://git.the-compiler.org/qutebrowser/commit/?id=0abb5cf7384c1ccfb2b829cbf26fcc92add08bc6) (für den ursprünglichen Absturz, nicht das minimale Beispiel)) sieht vernünftig aus? –
Gern geschehen :) Ich habe einen Blick in Ihren Code geworfen, aber ich habe es tatsächlich nicht getestet. Wie ich bereits im Tutorial erwähnt habe, ist diese "deleteLater" -Methode ebenfalls async, was passieren könnte, ist, dass Ihre 'shutdown' Methode beendet ist,' deleteLater' geplant ist, und die App beendet wird. aber die Objekte werden nicht so schnell gelöscht. Ich löste es, indem ich das 'zerstörte' Signal mit einer Methode verband, wo ich überprüfe, ob alle Komponenten erfolgreich gelöscht wurden, und erlaube der App dann nur zu beenden. – andrean
Du hast Recht, ich habe nicht daran gedacht. Das habe ich jetzt auch umgesetzt (http://git.the-compiler.org/qutebrowser/commit/?id=8c37e1c33a11fdcb26ac985b72fae27e083b158a), und zumindest in meinen (wenigen) Tests bisher keine segfaults. –