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.
-
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.
-
[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