PyQt5 QThread Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

Maurizio Berti maurizio.berti at gmail.com
Thu Jul 1 23:58:12 BST 2021


Il giorno gio 1 lug 2021 alle ore 08:54 Giuseppe Corbelli <
corbelligiuseppe at mesdan.it> ha scritto:

> Well, since no synchronization is provided this is no surprise and holds
> true for everything that runs multithreaded.
>

Yes, but since most people don't really understand how threading and UI
work, it's still important to make this "higher level" point very clear.
Event driven systems are so transparently used that users are often led to
believe that different windows (or UI elements) can work independently, and
can thus be created/accessed from other threads.


> Very good point indeed. If you don't need an event loop (so no signals
> delivery) then there's no point in using QThread instead of plain
> threading module but you're absolutely right.
>

Indeed, a QThread makes sense whenever any interaction with (and, most
importantly, *to*) the UI is required. If we're not interested in the
actual "output" of the thread to be in any way "notified" through the UI, a
standard python thread will suffice.
The aspect of signal delivery depends on the direction: signals might still
be required even without an event loop, but, still, an event loop is
conceptually just something that runs (or "waits") until something happens:
even a simple time.sleep() (without any while/for) can be considered as an
event loop: it waits until the time has elapsed ;-)
An important aspect that should always be kept in mind and really helps the
implementation is that a "worker" (or, better, "non-main") thread should
usually be "self contained", and know nothing about the UI it is "working
for". It is a compartmentalised object that should really work on its own,
do its job, possibly wait for some input to do that job (but it doesn't
need to know about the source of that input), and then tell the results of
that job to "anything listening" to it, no matter what.

> - for the same reason, it's not possible to connect the started signal
> > to a function of a QObject instance that exists in the main thread: it
> > would require moving the object to the thread, which is not allowed, and
> > the result is that the signal will be queued and then the function will
> > be executed in the receiver thread;
>
> I didn't understand this one. The started() signal of a QThread can be
> connected to a slot in any thread and the slot executed in the thread
> affine to the slot QObject.
>

Yes. As long as the QObject is moved to a QThread (*any* QThread), the slot
is executed in that thread.
The started() signal behaves just like any signal, *but* while it is sent
from the QThread emitting the signal, the *thread* of the emission is that
on which the QThread is wrapped around.
So, when the thread is started, the started() signal is emitted from that
QThread, but in the thread that QThread is wrapped around; then, if the
thread of the receiver is on another thread (typically, by using
moveToThread), the function will be executed in that target thread.

This can be very confusing, I know. The fact is that moveToThread actually
means "move to the thread that is managed by that QThread". That's why you
can actually use moveToThread on the QThread (self.moveToThread(self)),
which is probably one of the reasons for the confusion that caused the
infamous Qt blog post.



> > Finally, you could still subclass a QThread and implement a "worker
> > function" in that thread (thus allowing the default implementation to
> > execute and use the thread's event loop): just give it a different name
> > and connect it to the started signal.
>

An important clarification about this: in order to *actually* run a worker
function in the thread of a QThread subclass, that QThread requires moving
it to itself (as explained above). This is an important aspect that wasn't
properly explained in my previous message.


> On this subject I would suggest looking at QRunnable and QThreadPool as
> they provide an higher level interface for background workers that don't
> need much interaction
>

QRunnable is a very interesting interface, but has the obvious drawback of
not being a QObject subclass, so it doesn't support signals. Its concurrent
reusability, though, is a major benefit, and adding a *single* QObject
"proxy" within a unique QRunnable instance can be really useful, if
properly implemented.


Let me say thank you for writing down this exhaustive analysis (which
> admittedly is far better than my 2 lines answer).
>

You're very welcome :-) I learnt all this "the hard way", so it seems only
obvious to me to share my experience with others. It took me a lot of time
to understand all these aspects on my own, and writing such answers also
helps me to even dig deeper in that knowledge, so it actually brings
benefits to myself too...

Maurizio
-- 
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20210702/c6e03054/attachment.htm>


More information about the PyQt mailing list