使用 PyQt 和信号在 qt5serialport.dll 中获取段错误

Posted

技术标签:

【中文标题】使用 PyQt 和信号在 qt5serialport.dll 中获取段错误【英文标题】:Getting segfault in qt5serialport.dll with PyQt and signals 【发布时间】:2013-12-06 09:18:28 【问题描述】:

我目前正在努力解决在 Windows XP SP3、Python 3.3.3 和 PyQt5 5.1.1 中使用 QSerialPort 并发出信号时遇到的奇怪段错误。

我真的很想知道这是否也发生在带有 C++ 的纯 Qt 中,但是我的 C++ 很糟糕,而且我没有设置正在运行的工具链。

最小的示例代码(抱歉,无法简化更多):

#!/usr/bin/python

import sys

from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
from PyQt5.QtCore import QObject, pyqtSlot, QIODevice, pyqtSignal
from PyQt5.QtSerialPort import QSerialPort

PORT = 'COM59'

class DVIFlasher(QObject):
    ser = None
    flash_done = pyqtSignal(int, int)

    def __init__(self):
        super(DVIFlasher, self).__init__()
        self.ser = QSerialPort(PORT)
        self.ser.readyRead.connect(self.read)

    def flash(self):
        print(self.ser.open(QIODevice.ReadWrite))
        self.ser.setBaudRate(115200)

    def read(self):
        print("Got data")
        self.ser.close()
        self.flash_done.emit(0, 0)

class Widget(QWidget):
    def __init__(self):
        super(Widget, self).__init__()
        self.btn = QPushButton("Start", self)
        self.flasher = DVIFlasher()
        self.btn.clicked.connect(self.flasher.flash)
        self.resize(self.btn.sizeHint())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Widget()
    win.show()
    sys.exit(app.exec_())

当我运行它并通过串行端口接收一个字节时,我在 qt5serialport.dll 中得到一个“访问冲突”(又名 segfault)。有时在第一次单击“开始”时会发生这种情况,有时会在第二次单击“开始”后发生。

到目前为止我观察到的一些事情:

信号需要有一个 bool/int 作为第一个参数,以及其他一些参数——否则它似乎不会触发。

当我发出信号之前端口已关闭(self.ser.close()),它似乎没有触发。

在 Linux(Archlinux、Python 3.3.2、PyQt 5.1.1)上我无法重现此问题,但在第二次启动后,我总是收到 QSocketNotifier: Invalid socket specified

什么给了?难道我做错了什么?或者这是某个地方的 [Py]Qt 中的错误?

【问题讨论】:

不知道您是否解决了这个问题?如果没有,您能否提供包含调试符号的崩溃回溯? @LaszloPapp 我在发出信号后通过ser.close() 解决了这个问题。这里有人提到它可能是一个特定的 Qt 错误(而且看起来非常相似),但他的评论现在已经消失了......我不知道如何安装带有调试符号的 Qt/PyQt 并在 Windows 下获得跟踪,但我怀疑这不会太容易...... 【参考方案1】:

你面对的是this bug。这是一个相对古老的问题并且众所周知。如果幸运的话,它可以在 5.2.1 中修复。您在 readyRead 信号处理程序中不调用 ser.close() 的解决方法看起来很合理。

希望,这会有所帮助。

【讨论】:

确实在我的信号处理程序中调用ser.close(),就在最后,这似乎有效。 @TheCompiler:请不要那样做。它目前具有未定义的行为,主要被识别为崩溃。 你说得对,经过一些重构,我现在得到“... .exe funktioniert nicht mehr”(字面意思是“不再工作”,但不确定英文信息是什么)。但是当我在插槽中设置一个标志并使用我的 MainWindow 中的 QTimer 关闭串行端口时,会发生同样的事情!目前没有时间收集更多信息,但会在假期后尝试。 @TheCompiler:好的,好好休息。 没关系——它确实与 MainWindow 中的 QTimer 一起工作,我只是忘了实际从插槽中删除 ser.close()

以上是关于使用 PyQt 和信号在 qt5serialport.dll 中获取段错误的主要内容,如果未能解决你的问题,请参考以下文章

PyQt 信号和插槽:“新风格”发射?

使用 PyQt 和信号在 qt5serialport.dll 中获取段错误

PyQt5——信号和槽初探

PyQt:QListView 拖放重新排序信号问题

网址未使用不同类中的信号和插槽 PyQt5 定义

PyQt5 数据在字节类型的信号发射期间丢失