Multithreading PySide、pySerial和线程导致SEGFULT

Multithreading PySide、pySerial和线程导致SEGFULT,multithreading,qt,segmentation-fault,pyside,pyserial,Multithreading,Qt,Segmentation Fault,Pyside,Pyserial,我正在尝试使用PySide和pySerial来制作一个与串口交互的跨平台应用程序。我最初使用qtimer轮询串行数据,但这给cpu带来了很大的负载。所以我一直在尝试使用线程 不幸的是,使用线程会导致Qt或pySerial出现故障 我试过python线程和QThreads,同样的问题,它发生在OSX、Windows8和Ubuntu12.04上。使用Python2.7和Qt4 下面是一个小应用程序,它重现了这个问题 #! /usr/bin/python import sys import ser

我正在尝试使用PySide和pySerial来制作一个与串口交互的跨平台应用程序。我最初使用qtimer轮询串行数据,但这给cpu带来了很大的负载。所以我一直在尝试使用线程

不幸的是,使用线程会导致Qt或pySerial出现故障

我试过python线程和QThreads,同样的问题,它发生在OSX、Windows8和Ubuntu12.04上。使用Python2.7和Qt4

下面是一个小应用程序,它重现了这个问题

#! /usr/bin/python
import sys
import serial
import threading
from PySide import QtCore, QtGui, QtUiTools

class serial_port_class(object):
    def __init__(self, ui):
        self.ui = ui
        self.connected = False

    def __del__(self):
        self.disconnect_port()

    def connect_port(self):
        try:
            self.serial_port = serial.Serial("/dev/tty.usbmodem1451", 9600, timeout = None)
            self.connected = True
        except serial.SerialException, e:
            self.connected = False
        if self.connected:
            self.serial_thread = threading.Thread(target=self.recieve_port, args=([self.ui]))
            self.serial_thread.start()

    def disconnect_port(self):
        self.connected = False
        self.serial_thread.join()
        self.serial_port.close()

    def recieve_port(self, ui):
        while self.connected:
            try:
                text = self.serial_port.read(1)
                if text != '':
                    ui.plain_edit.appendPlainText(text)
            except serial.SerialException, e:
                connected = False

class KeyPressEater(QtCore.QObject):
    def eventFilter(self, obj, event):
        global serial_port
        if event.type() == QtCore.QEvent.KeyPress:  
            ch = event.text().encode('utf-8')
            if serial_port.connected == True:
                serial_port.serial_port.write(ch)
        return QtCore.QObject.eventFilter(self, obj, event)


def main():
    global serial_port
    app = QtGui.QApplication(sys.argv)
    ui = QtGui.QWidget()
    ui.plain_edit = QtGui.QPlainTextEdit(ui)
    keyFilter = KeyPressEater(ui)
    ui.plain_edit.installEventFilter(keyFilter)
    serial_port = serial_port_class(ui)
    serial_port.connect_port()
    ui.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
有时需要一点数据IO来触发segfault,有时一个字符就会触发它

我真的不确定如何进一步调试这个

感谢所有的帮助

更新
我用不同的硬盘重新创建了这个问题,并在

Qt对象不是线程安全的,所以调用

ui.plain_edit.appendPlainText(text)
从另一个线程是坏的

解决这个问题的一种方法是使用QThreads和内置的线程安全消息和事件系统 比如:

class receivePort(QThread):
    message = QtCore.Signal(str)
    def __init__(self):
        self.connected = False
        QThread.__init__(self)

    def run(self):
        while self.connected:
            try:
                text = self.serial_port.read(1)
                if text != '':
                    self.message.emit(text) 
            except serial.SerialException, e:
                connected = False  
并使用以下方法将其连接起来:

serial_thread = receivePort()
serial_thread.message.connect(write_terminal, QtCore.Qt.QueuedConnection)
serial_thread.start()
其中,write_终端具有以下签名:

def write_terminal(text):
    ui.plain_edit.appendPlainText(text)

如果您正在使用Qt,是否有任何原因不使用QtSerialPort?不确定pyside是否有绑定,尽管添加起来应该很容易。您是正确的,pyside没有QtSerialPort的绑定。我对解决这种情况比自己添加QtSerialPort绑定更感兴趣。由于其他人似乎也有类似的问题,我认为追踪原因并可能向任何一个项目提交错误报告都是有价值的。