[Interest] Help with QSslSocket race condition?

Thiago Macieira thiago.macieira at intel.com
Wed Oct 24 02:07:27 CEST 2018


On Tuesday, 23 October 2018 11:43:24 PDT Israel Brewster wrote:
> I am using QSslSockets with a QTcpServer to create a simple client/server
> program (is there a higher level API I could use instead?). I have
> subclassed QTcpServer to create my server side sockets as QSslSockets and
> call startServerEncryption(), but otherwise it is just a standard
> QTcpServer.

Hello Israel

> bool EZPCore::waitForResponseReady(QSslSocket *socket,int msec){
>     if(!socket || !socket->isValid() || !socket->isEncrypted() ||
> socket->state()!=QAbstractSocket::ConnectedState) return false; //there is
> something wrong with the socket, no point in waiting.
> 
>     if(socket->bytesAvailable()>0)
>         return true;//success! Bytes are available!
> 
>     QEventLoop wait;  //don't block other operations while waiting
>     QTimer waitTimeout; //only wait a set length of time.
>     waitTimeout.setSingleShot(true);
> 
>     connect(&waitTimeout,&QTimer::timeout,[&wait]{wait.exit(-1);});
>     connect(socket,&QAbstractSocket::disconnected,[&wait]{wait.exit(-2);});
> //catch if the socket closes while waiting.

This is too late.

> connect(socket,&QAbstractSocket::readyRead,[&wait]{wait.exit();}); //zero
> exit
> 
>     waitTimeout.start(msec);
>     int result=wait.exec();
>     waitTimeout.stop(); //stop the timer if it is still running (probably
> unneeded?)
> 
>     if(result<0)
>         return false; //not connected or timeout
> 
>     //should only get here if result is 0, indicating readyRead signal
> received.
> 
>     //if we have bytes available, then return success (0), even if
>     //we had a timeout
>     if(socket->bytesAvailable()>0) //<--------We frequently crash here,
> UNLESS I don't call "deleteLater()" on disconnect??? 
>         return true;
>     return false; //no bytes available
> }

>From what I can see, the socket got disconnected by the remote end, with new 
data. So BOTH the readyRead() and disconnected() signals got emitted. Both as 
well as bytesWritten() are handled by the same loop, so any one of the three 
or all three can be emitted by an iteration of the event looop. However, 
there's only one QEventLoop exit code and readyRead() happened first.

> - When I come into this function, I check for
> QAbstractSocket::ConnectedState on the socket, and return immediately if
> not connected, which should mean that the socket is still connected when
> this function starts. 

Right.

> - I connect the "disconnected" signal of this
> function up to exit the event loop with a non-zero status should the socket
> disconnect during the event loop (entirely possible, of course) 

Only if it disconnected without receiving any data in the same loop.

> - The
> function returns immediately if the event loop exits with a non-zero
> status, and the only way for the event loop to exit with a zero status is
> for readyRead to be emitted.
> 
> As such, the only way for the crashing line of code to be executed should be
> for a) the socket to be in a connected state (otherwise the function
> wouldn't run), b) disconnected signal to NOT to be emitted during the event
> loop (so still connected), 

Incorrect. It must have been emitted.

> and c) the readyRead signal to be emitted.
> However, the crashing would indicate that the socket *is* being deleted
> during the event loop, which indicates that the socket is disconnecting.
> And yet I still get a readyRead signal?

Correct, you do.

> Incidentally, If I connect the destroyed signal to the event loop exit, I
> *do* catch that. So I can see the socket being destroyed, but not being
> disconnected. 

It is being disconnected, you're just not seeing the events in the right order 
due to nesting.

> So obviously I have an architecture issue here: the socket is
> closing and being destroyed while I am still trying to read from it. How
> can I fix this?

Remove this waitForResponseReady() function entirely and all uses of 
QEventLoop.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center






More information about the Interest mailing list