Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slot running in IOLoop thread crash #23

Open
lkraider opened this issue Aug 21, 2014 · 8 comments
Open

Slot running in IOLoop thread crash #23

lkraider opened this issue Aug 21, 2014 · 8 comments

Comments

@lkraider
Copy link

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?

@PierreBizouard
Copy link
Collaborator

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.

@PierreBizouard
Copy link
Collaborator

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.

@hgrecco
Copy link
Owner

hgrecco commented Aug 22, 2014

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

@PierreBizouard
Copy link
Collaborator

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

@lkraider
Copy link
Author

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.

@hgrecco
Copy link
Owner

hgrecco commented Aug 25, 2014

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.

@PierreBizouard
Copy link
Collaborator

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

@PierreBizouard
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants