Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does PyQt crashes without information? (exit code 0xC0000409)

I'm trying to develop a software with PyQt, but I often get stuck on software crashes without debug information (only the exit code 0xC0000409). I'm using QThread, and I wrote a system like this:

class serialThreadC(QThread):
    updateOutBox = QtCore.pyqtSignal(str)
    updateStatus = QtCore.pyqtSignal(int)

    def __init__(self):
        super(serialThreadC, self).__init__()
        self.ser = False
        self.state = 0
        self.serialEnabled = False

    def run(self):
        while True:
            if self.state == -3 or self.state == -2:
                if self.SerialEnabled:
                    self.updatePB(20)
            elif self.state == 0:
                if self.serialEnabled:
                    self.updatePB(20)

    def ConnDisconn(self):
        self.serialEnabled = not self.serialEnabled

    def updatePB(self, stat):
        self.state = stat
        self.updateStatus.emit(self.state)

serialThread = serialThreadC()
serialThread.start()

## sw is a QDialog already loaded
serialThread.updateOutBox.connect(sw.updateOutBox)
serialThread.updateStatus.connect(sw.updateStatus)

sw.PB_ConnDisconn.clicked.connect(serialThread.ConnDisconn)

I have crashes when I read/write serialEnabled in run() or in ConnDisconn(). I know that PyQt is not thread-safe and that a wrong handling of variables gives crashes of my type, but I can't understand what is wrong with my code. My idea (maybe wrong) is that all serialThread methods are executed on the same thread, also if they are connected to a gui (main thread). Is that wrong? In the same way, I emit events from serialThread and I connected them to the GUI, but that never gave me problems.

Can you see the mistake I made? Is there a way to debug the code if there is a crash without other infos? (I use PyCharm 2017.1.3).

like image 751
brazoayeye Avatar asked Oct 12 '17 13:10

brazoayeye


People also ask

Is PyQt thread safe?

Is PyQt thread safe? Remarks# While some parts of the Qt framework are thread safe, much of it is not. The Qt C++ documentation provides a good overview of which classes are reentrant (can be used to instantiate objects in multiple threads).

What is Process finished with exit code 0xC0000005?

0xC0000005 is a code for Access Violation error. It means that your program just tried to read, or write, in a section of memory that it has no access to. Most likely, this happened due to poor usage of pointers. Since your program does not have access to the address 0x0000000, this will cause error 0xC0000005.


1 Answers

PyQt is thread-safe to the same extent that Qt is thread-safe. The Qt docs will tell you which parts of their API are guaranteed to be so, and under what circumstances.

Cross-thread signals are thread-safe, so calling the updatePB method in your example is okay. Your ConnDisconn method is not thread-safe, but that has got nothing to do with PyQt or Qt - it's just a consequence of how you wrote it. The serialEnabled attribute could be read/written by two threads simultaneously, so the behaviour is strictly undefined. A thread-safe way of writing this would be to use a mutex, like so:

class serialThreadC(QThread):
    updateOutBox = QtCore.pyqtSignal(str)
    updateStatus = QtCore.pyqtSignal(int)

    def __init__(self):
        super(serialThreadC, self).__init__()
        self.ser = False
        self.state = 0
        self._mutex = QMutex()
        self.serialEnabled = False   

    def ConnDisconn(self):
        self._mutex.lock()
        self.serialEnabled = not self.serialEnabled
        self._mutex.unlock()

    def run(self):
        while True:
            if self.state == -3 or self.state == -2:
                self._mutex.lock()
                if self.serialEnabled:
                    self.updatePB(20)
                self._mutex.unlock()
            elif self.state == 0:
                self._mutex.lock()
                if self.serialEnabled:
                    self.updatePB(20)
                self._mutex.unlock()

(NB: if you're using any kind of IDE or debugger, and you are getting unexpected errors or crashes, your first step in diagnosing the problem should always be to test the code in a standard console. Quite often, the IDE or debugger itself can be the cause of the problem, or may mask error messages comming either from Python or from underlying libraries, such as Qt).

like image 154
ekhumoro Avatar answered Oct 13 '22 08:10

ekhumoro