PySide QThread.terminate() causing fatal python error



  • I am using PySide version 1.2.2, which wraps the Qt v4.8 framework. I am in a situation where I have to choose between having my application wait for a QThread that I no longer need to exit normally (it is quite possible that the thread will block indefinitely), and giving the unresponsive thread a grace period (of several seconds), then calling QThread.terminate() on it. Though I wish I could, I cannot let the QThread object go out of scope while the underlying thread is still running, since this will throw the error "QThread: Destroyed while thread is still running" and almost surely cause a segfault.

    Please note that I am aware that terminating QThreads is dangerous and highly discouraged. I am just trying to explore my options here.

    When I try to terminate a thread however, my application crashes with the following error:

    bq. Fatal Python error: This thread state must be current when releasing

    You can try this out yourself by copy/pasting and running the following code:

    @from PySide import QtCore, QtGui

    class Looper(QtCore.QThread):
    """QThread that prints natural numbers, one by one to stdout."""
    def init(self, *args, **kwargs):
    super(Looper, self).init(*args, **kwargs)
    self.setTerminationEnabled(True)

    def run(self):
        i = 0
        while True:
            self.msleep(100)
            print(i)
            i += 1
    

    Initialize and start a looper.

    looper = Looper()
    looper.start()

    Sleep main thread for 5 seconds.

    QtCore.QThread.sleep(5)

    Terminate looper.

    looper.terminate()

    After calling terminate(), we should call looper.wait() or listen

    for the QThread.terminated signal, but that is irrelevant for

    the purpose of this example.

    app = QtGui.QApplication([])
    app.exec_()
    @

    How do you properly terminate QThreads in python? I reckon that the error I am getting has got something to do with releasing of the Global Interpreter Lock, but I am not sure exactly what is going wrong, and how to fix it.



  • Hi,

    There is a dedicated forum for "language bindings":http://qt-project.org/forums/viewforum/15/. You may get a better answer there.


  • Lifetime Qt Champion

    Hi,

    Topic moved

    On to your question: terminate and properly do not belong together. You should write your thread so that you can exit/quit it properly. The documentation of QThread also explains that termination can lead to unexpected results.

    @
    class Looper(QtCore.QThread):
    """QThread that prints natural numbers, one by one to stdout."""
    def init(self, *args, **kwargs):
    super(Looper, self).init(*args, **kwargs)
    self.setTerminationEnabled(True)

    def stop(self):
         self.continue = False
    
    def run(self):
        i = 0
        self.continue = True
        while self.continue:
            self.msleep(100)
            print(i)
            i += 1
    

    @

    Something like that and you can stop it gracefully



  • @SGaist I am already using flags as you suggested. The operation that is taking too long is a library function call that I have little control over. I am looking to understand why I cannot terminate() QThreads in PySide.


  • Moderators

    [quote author="nullstellensatz" date="1421370989"]The operation that is taking too long is a library function call that I have little control over.[/quote]That's unfortunate. Any chance of getting the library's author to provide a better API?

    [quote]I am looking to understand why I cannot terminate() QThreads in PySide.[/quote]Not sure (I don't have Python experience), but judging from your error message, I'm guessing it's related to how PySide handles the "Global Interpreter Lock":https://docs.python.org/2/c-api/init.html#thread-state-and-the-global-interpreter-lock


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.