hgrecco / pizco

Pizco is Python module/package that allows python objects to communicate via ZMQ. Objects can be exposed to other process in the same computer or over the network, allowing clear separation of concerns, resources and permissions.

Home Page:https://pizco.readthedocs.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Slot running in IOLoop thread crash

lkraider opened this issue · comments

I have a PyQt5 app which is connecting with signals through Pizco, and I am getting crashes when trying to update a progress bar.

Inspecting the current_thread inside the slot call, it shows:

$ python app.py
progress 0 thread: <_MainThread(MainThread, started 140735239987984)>
progress 0.0 thread: <_MainThread(MainThread, started 140735239987984)>
progress 0.0 thread: <_MainThread(MainThread, started 140735239987984)>
progress 10.0 thread: <_MainThread(MainThread, started 140735239987984)>

progress 0.0 thread: <Thread(ioloop-4597532432, started daemon 4603047936)>
QWidget::repaint: Recursive repaint detected
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
Segmentation fault: 11 (core dumped)

I am connecting the signals as shown in the example app. Updating QLabels do not cause a crash, but I am guessing it should actually be all run from the main thread.

What is the correct way here? Should I have a model that is updated by the IOLoop thread by the proxy signals, and then connect GUI slots to it so it runs from the main thread?

I believe that the signal should be emitted from a Qthread. So there must
be an adapter in a herited signal class that does the trick of creating the
pyqtSignal in a Qthread and calling emit instead of the slot. Maybe by
checking the pyqtSlot decorator presence at the slot connexion.

I have issues of the same kind, so i have a qt dependent part of pizco
called pizco-utils.
Le 22 août 2014 01:45, "Paul Eipper" notifications@github.com a écrit :

I have a PyQt5 app which is connecting with signals through Pizco, and I
am getting crashes when trying to update a progress bar.

Inspecting the current_thread inside the slot call, it shows:

$ python app.py
progress 0 thread: <_MainThread(MainThread, started 140735239987984)>
progress 0.0 thread: <_MainThread(MainThread, started 140735239987984)>
progress 0.0 thread: <_MainThread(MainThread, started 140735239987984)>
progress 10.0 thread: <_MainThread(MainThread, started 140735239987984)>

progress 0.0 thread: <Thread(ioloop-4597532432, started daemon 4603047936)>
QWidget::repaint: Recursive repaint detected
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
Segmentation fault: 11 (core dumped)

I am connecting the signals as shown in the example app. Updating QLabels
do not cause a crash, but I am guessing it should actually be all run from
the main thread.

What is the correct way here? Should I have a model that is updated by the
IOLoop thread on the proxy signals, and then connect GUI slots to it so it
runs from the main thread?


Reply to this email directly or view it on GitHub
#23.

I have +in mind
Le 22 août 2014 01:45, "Paul Eipper" notifications@github.com a écrit :

I have a PyQt5 app which is connecting with signals through Pizco, and I
am getting crashes when trying to update a progress bar.

Inspecting the current_thread inside the slot call, it shows:

$ python app.py
progress 0 thread: <_MainThread(MainThread, started 140735239987984)>
progress 0.0 thread: <_MainThread(MainThread, started 140735239987984)>
progress 0.0 thread: <_MainThread(MainThread, started 140735239987984)>
progress 10.0 thread: <_MainThread(MainThread, started 140735239987984)>

progress 0.0 thread: <Thread(ioloop-4597532432, started daemon 4603047936)>
QWidget::repaint: Recursive repaint detected
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
Segmentation fault: 11 (core dumped)

I am connecting the signals as shown in the example app. Updating QLabels
do not cause a crash, but I am guessing it should actually be all run from
the main thread.

What is the correct way here? Should I have a model that is updated by the
IOLoop thread on the proxy signals, and then connect GUI slots to it so it
runs from the main thread?


Reply to this email directly or view it on GitHub
#23.

Can you post a gist with the minimal code that crashes. I think that Pierre is right but it will be nice to check.

Here are a few relevant links to our problem :

http://trevorius.com/scrapbook/python/binding-singals-dynamically/

http://abstractfactory.io/blog/dynamic-signals-in-pyqt/

It appears that the Qthread's signal should have a generic (list,dict)
signature. That connect to another QObject whose slots (with list,dict
signature) reside in the MainThread, and which calls the resynchronized
slots from the base signal class. So we should end with the actual class
calling partial.

I would be please to have the code, but I don't have the time yet.

2014-08-22 8:26 GMT+02:00 Hernan Grecco notifications@github.com:

Can you post a gist with the minimal code that crashes. I think that
Pierre is right but it will be nice to check.


Reply to this email directly or view it on GitHub
#23 (comment).

I solved it for now by having a model class (subclassed from QObject) that receives the pizco proxy calls, stores the data and re-emits as pyqtSignals. This solves the mainthread GUI update problem.

The model is mostly boilerplate code (getters/setters), so it probably can be solved from pizco side for most common use cases.

I'll see about providing a simple test-case.

I would be great to incorportate this and pizco-utils in the master as soon as you feel confortable with it. My only request is that Pizco does not require PyQt (nor PySide). But I am happy to add utilities that help to make good use of it if present.

yep I understand the need to not need pyqt :) i have allready some pseudo
code for SignalResync class.

2014-08-25 8:05 GMT+02:00 Hernan Grecco notifications@github.com:

I would be great to incorportate this and pizco-utils in the master as
soon as you feel confortable with it. My only request is that Pizco does
not require PyQt (nor PySide). But I am happy to add utilities that help to
make good use of it if present.


Reply to this email directly or view it on GitHub
#23 (comment).

Hello for info :

https://github.com/PierreBizouard/pizco-utils/blob/master/pizcoutils/signal_resync.py

The tests requires some exotic but nice packages to run (guiqwt)

It also solves the dynamic qt signal creation issue