0

I have a custom-built player which can "play" recoded media samples (sensor data with timestamps).

What I am trying to do is couple this player to an Qt UI. I have created a Widget and coupled the Player and the Widget through Signals and slots (Qt::DirectConnection).

The problem I'm experiencing is that the program crashes with an exception thrown. The moment when it crashes is completely random, and sometimes it may not crash. As far as I can tell, the problem lies in that the update in the widget part is not thread-safe. I have tried restricting access to it with a binary semaphore (immediately return if semaphore true, continue if not). The error still doesn't go away.

My question is: is the Qt Painter running on the same thread as the Widget updater? I suspect I'm calling the painter before the previous paint operation has finished, which is why it still crashes. I suspect the widget only somehow posts an event to the painter (non-blocking)..

What else could be the problem? Unfortunately, the code is too complex to paste here. However, I am attaching a screenshot of the crash.

Cheers, Mihai

enter image description here

Mihai Galos
  • 1,707
  • 1
  • 19
  • 38
  • 1
    Are you forcing Qt::DirectConnection for signals and slots between different threads? If so, this is likely one possible reason for the random crashes. – TheDarkKnight Sep 09 '14 at 09:56
  • 1
    If you want to paint on a widget, you should reimplement paint event. This is only good way for drawing. All GUI-related things will occur in a thread in which object was created. All GUI related things should be in main thread. And check that all objects are actually alive and you don't have memory leaks. – cassandrad Sep 09 '14 at 11:26
  • Thank you for your suggestions. Merlin069, the wiring is as follows: connect( this, SIGNAL(updateStatusTree(tUInt64,tUInt64,int)),_widget,SLOT(updateStatusTree(tUInt64,tUInt64,int)), Qt::DirectConnection ); I have tried changing it to Qt::QueuedConnection. The update method on the Widget side never gets called anymore.. – Mihai Galos Sep 09 '14 at 11:53
  • Is `this` an object that lives in a different thread from the main thread? If so, what is it doing with a `_widget` pointer? – thuga Sep 10 '14 at 06:24
  • "this" is the player object reference. It's connecting the current player object signal to the widget object slot. – Mihai Galos Sep 10 '14 at 07:10
  • And does the player object live in the main thread? – thuga Sep 10 '14 at 08:18
  • the Player object is independet from the UI Thread. – Mihai Galos Sep 10 '14 at 12:36
  • In that case having a pointer to a widget is quite dangerous. Also specifying connection type is unnecessary as the default is [`Qt::AutoConnection`](http://qt-project.org/doc/qt-5/qt.html#ConnectionType-enum), which will check the thread affinity of the receiver during signal emission, and decide the connection type based on that. As to why the slot doesn't work when you use `Qt::QueuedConnection` it is hard to tell. I'm assuming nothing is blocking the event loop? – thuga Sep 10 '14 at 14:05

1 Answers1

0

Thank you for your precious feedback. I have managed to find the root cause for the problem. It was tied to the Qt::DirectConnection. As described in the API documentation, this will be executed:

"in the emitter's thread, which is not necessarily the receiver's thread."

In my case, the emitter is the Player and the receiver is the UI thread. Which means I'm manipulating elements in the UI outside of the UI Thread. This is the root cause.

I have changed the implementation to used Qt::QueuedConnection and now it runs smoothly.

As to why the original implementation with Qt::QueuedConnection did not work initially, I put a bool status = connect() which always returned false, meaning the connection failed. I changed the name of the signal method to be different from the name of the slot one (initially, they were the same), + I defaulted all the input parameters to standard types (unsigned int instead of tUInt32) and it worked. connect() now returns true. I suspect that somehow the connect() got confused as to the wiring..

Mihai Galos
  • 1,707
  • 1
  • 19
  • 38
  • 1
    Did you register your custom type with [`qRegisterMetaType`](http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType)? When you use slots with `Qt::QueuedConnection` connection type, you must register your custom type. – thuga Sep 12 '14 at 05:40