Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why a new signal for socket::readyRead() is executed, even when its earlier slot is still processing?

According to following post an emitted signal is served, only once the currently executing slot completes.
Wait for a SLOT to finish the execution with Qt

I have a client-server communication app based on ssl socket, which is single threaded.

connect(socket, &QSslSocket::readyRead, [&]() { myObject.Read(); });

Client & server send each other some custom messages. Whenever a message is sent or received by either, they send ACK bytes (00).
Most of the times, I notice that when the Read() is in between of execution, the next readyRead() is served! I put debug statements in beginning & end of myObject->Read(). They confirm that, beginning debug is called again & again. Same is observed with breakpoints.

When too much of data is received, a recursive stack frame is created of too many Read()s. It either slows down the app GUI or crashes.
Typically this recursion happens, when client attempts to send an ACK as part of myObject->Read(). During that time readyRead() is incidentally signalled & also gets served. However the slot of previous signal was still under processing.

Questions:

  • Is it possible for Qt framework to cater a signal in between when a slot is still mid-way (single thread)?
  • How to fix this socket specific scenario?

Note:
- By default for single threads, the Qt::ConnectionType is DirectConnection. I have tried with QueuedConnection as well, but the result is same.
- myObject.Read() is quite complex and has many other function calls. If this is causing problem, then let me know what should I look for. It will be impractical to write the actual code of it.

like image 874
iammilind Avatar asked Oct 05 '17 01:10

iammilind


1 Answers

The recursive calls of readyRead() were happening because of the event loop getting freed up in between. Following functions were causing the event loop to be freed:

  1. QCoreApplication::processEvents()
  2. SslSocket::flush()

The 1st is understandable, as it's meant for that. But the 2nd flush() was a total surprise. Its documentation doesn't state so. At least in my debugging it was showing that, whenever the flush() is invoked, the subsequent readyRead() is invoked and catered. See that in the Qn as well.

The processEvent() was meant to make GUI more responsive during the high loading of the data. But it seems that, we need to make another choice for the same.

like image 119
iammilind Avatar answered Nov 15 '22 15:11

iammilind