gpt4 book ai didi

python - PyQt:使用 QApplication.quit 时偶尔出现段错误

转载 作者:太空狗 更新时间:2023-10-30 00:50:28 25 4
gpt4 key购买 nike

注意:我还在 PyQt 邮件列表上发布了这个——如果那里有好的答案,我会在这里回答我自己的问题。

我在执行时遇到偶尔出现段错误的问题QApplication.quit(),可能与 libQt5Network.so 和/或QtWebkit.

首先,我正在使用的 3 个测试系统:

  • 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
  • Windows 7、PyQt 5.2、Qt 5.2.0、Python 3.3.3

到目前为止,这些崩溃在 Arch 上从未发生过,在Ubuntu,有时在 Windows 中。 (虽然 Windows 只是一个我猜,我只是得到这个 python.exe 不再工作了 foo。)

原始崩溃

我首先注意到一个大(ger)项目中的问题,qutebrowser ,在输入 :quit(在 Ubuntu 上)时它给了我这个堆栈跟踪:

#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)。

最小示例

然后我又尝试了一个最小的例子,它自己退出了一秒钟后自动使用 QTimer。我不得不循环运行它在它发生之前大约一分钟左右:

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_()

这给了我这个非常相似的堆栈跟踪(在 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)。

有人知道那里出了什么问题吗?一些神奇的东西以错误的方式被垃圾收集?我也尝试了一些PyQt4 上类似症状的变通办法*,但事实并非如此帮助。

* 在描述它的地方找不到 StackOverflow 答案 --基本上将 QtWidgets.qApp 设置为之前的 QApplication 实例运行 exec_(),然后到 None

最佳答案

我一直致力于在 PyQt/PySide 中捕获段错误已有一段时间了。基本上,我发现大多数段错误都可以归咎于库的异步性质(因此也归咎于我们)。

对于您的确切示例,您已将 timeout 信号连接到 quit 方法。这里可能发生的情况是,如果发生超时,将调用quit,并且当进程终止时,突然所有对应用程序对象的引用都无效。但是当这个操作发生时,QT 的事件循环仍在运行,并且它试图访问它的 QNetworkAccessManager 以分派(dispatch)另一个信号,但是对该内存位置的引用是已经无效,因此发生了段错误。

在这些情况下需要做的是实现一种关闭方法,这将确保停止所有操作,删除您正在使用的 QT 组件命令,然后,就在这时,调用允许退出。

我在这里更详细地介绍了这个主题,包括 QtWebKit 应用程序的安全关闭方法:https://github.com/integricho/path-of-a-pyqter/tree/master/qttut08

关于python - PyQt:使用 QApplication.quit 时偶尔出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21713682/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com