Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[pyqt] Slot crashed in secondary thread without error and works in GUI thread



  • Hi,

    I have an application with 2 threads. One for the main GUI and another used for heavy computations.
    This works quite ok but I have one slot that makes my application crashing without any error when executed in the secondary thread. If I execute it in the GUI thread, there is no problem...

    Any idea on :

    • How to fix it
    • How to get more information about the crash

    Here is the code I am running, I figured out that the call the the library thorlabs_apt causes the crash. This is a library controlling some mechanical equipments via USB. (mainly motors).
    The library is on GitHub

    I use the function moveToThread. When using the decorator @pyqtslot() the function crashes, without that decorator, everything works fine.

    import thorlabs_apt as apt
    """
    Class definition and other slots
    """
    
     def InitConnection(self):
        self.measurementLog.emit("Starting measurement")
        try:
                thorlabs_stages_available = apt.list_available_devices()
                print(thorlabs_stages_available)
                for i in range(len(thorlabs_stages_available)):
                    if thorlabs_stages_available[i][1] == 49857638:
                        self.shutter = apt.Motor(thorlabs_stages_available[i][1])
                        self.measurementLog[str, loggingLevel].emit("Shutter detected", loggingLevel.SUCCESS)
                        self.shutter.set_velocity_parameters(0, 7, 2.5)
                        self.measurementLog.emit("Max shutter velocity set to 2.5")
    
                        self.measurementLog.emit("Homing shutter...")
                        self.shutter.move_home(blocking=True)
                        self.measurementLog.emit("Done")
    
                    elif thorlabs_stages_available[i][1] == 40834508:
                        self.nanorotator = apt.Motor(thorlabs_stages_available[i][1])
                        self.measurementLog[str, loggingLevel].emit("Nano rotator detected", loggingLevel.SUCCESS)
                        self.measurementLog.emit("Homing nanorotator...")
                        self.nanorotator.move_home(blocking=True)
                        self.measurementLog.emit("Done")
    
                    elif thorlabs_stages_available[i][1] == 83828364:
                        self.mz7 = apt.Motor(thorlabs_stages_available[i][1])
                        self.measurementLog[str, loggingLevel].emit("MZ7 detected", loggingLevel.SUCCESS)
                        self.measurementLog.emit("Homing mz7 analyzer...")
                        self.mz7.move_home(blocking=True)
                        self.measurementLog.emit("Done")
    
                self.thorlabs_connected.emit(True)
    
            except Exception as e:
                stages_connected = False
                print("Thorlabs stages initialization failed: {}".format(e))
    

    Thanks


  • Lifetime Qt Champion

    @Thombou Do you access any GUI elements form your non-GUI thread?



  • Hi,
    That's what I thought first but i don't think so looking at my code.
    The only non self variable I am using are locals to the function. I imported the apt library outside that thread but could that be the reason?


  • Lifetime Qt Champion

    Hi,

    To get more information about the crash you can use pdb or ipdb and start you script from there.



  • Hi,
    Same behavior when using ipdb, no error message.

    I found out tha tif I import he thorlabs_apt library from within the slots it works.
    How can it be? Is that something that often happen and shall I keep my code this way?
    This does not sound very "clean"...


  • Lifetime Qt Champion

    Can't you step in your code until the crash happens ?



  • @SGaist Yes I can. I see that the crashing line is self.shutter = apt.Motor(thorlabs_stages_available[i][1])

    But when executing this line it crashes and does not drop any error message...



  • Could it be because I instantiate an object of a class that has been defined in the main thread? How to do it in that case?


  • Lifetime Qt Champion

    @Thombou said in [pyqt] Slot crashed in secondary thread without error and works in GUI thread:

    I instantiate an object of a class that has been defined in the main thread?

    What does that mean? If you create the instance in the correct thread then all is fine. A class is not "defined" in a thread.



  • @jsulm said in [pyqt] Slot crashed in secondary thread without error and works in GUI thread:

    @Thombou said in [pyqt] Slot crashed in secondary thread without error and works in GUI thread:

    I instantiate an object of a class that has been defined in the main thread?

    What does that mean? If you create the instance in the correct thread then all is fine. A class is not "defined" in a thread.

    Technically, a class definition does happen within a particular thread in python or likely any other interpreted language. It's possible that the definition creates or captures a QObject reference, making the class unusable from other threads.

    The same general hazard is possible in C++ with lambda objects with captures, use of global QObjects, and likely additional scenarios.

    I don't have any reason to suspect the OP is doing this. If I'm wrong, stop doing this!



  • @Thombou You might learn more by attaching a C++/native code debugger to the running process. After the process stops, allow it to continue and trigger the crash. Or set breakpoints in Qt or any other native code that might be of interest.


Log in to reply