PDA

View Full Version : QTcpSocket error signal emitted twice



CactusPie
20th February 2013, 00:17
I am having an odd problem with QTcpSocket error signal. I define new socket like this:


socket = new QTcpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(ReceivedPacket()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(connectionError(QAbstractSocket::SocketError) ));

And everything works fine, until an error appears. Let's say I'm gonna try to connect to a host that doesn't accept connections on the port I'm trying to connect to. Error singal will be emitted, and after about 1 second there will be another one. Inside the error slot I have the following piece of code:



if(socket)
{
delete socket;
socket = NULL;
}

But it still causes server crashes (due to a double free) and the error message is displayed twice.
The entire code is a little bit longer, but it is available here: http://pastebin.com/9CrdK95i

How can I prevent the error signal from being emitted/captured twice?

Could someone please help me?
Thank you in advance!

ChrisW67
20th February 2013, 01:35
You are assuming the call to connectToHost() is blocking. This is not the case. Qt networking calls are asynchronous and event driven, giving you signals when states change. The call schedules a series of events (look up host, attempt connect, connected) that will occur when the Qt event loop next processes, which does not happen until after the BCreateAccount_Clicked() routine completes. The write() call you make on the socket may queue data to be sent, but if the connect fails (#1) it may then generate a separate error (#2) because the data cannot be written.

You are also assuming that any response will be received in one packet. This is very unlikely to be the case except if the response is very small. Your code expects only 4 bytes, but think what would happen if only 3 bytes were delivered.

Do not delete the socket inside a slot handling signals emitted by the socket: that is a good way to flirt with a crash. Use socket->deleteLater().

CactusPie
20th February 2013, 15:54
Thanks a lot! I fixed the problems you mentioned and now everything works fine.

As for the possiblity of response not being received in one packet, I know that. The packet itself is 8 bytes long, so during testing it shouldn't really casue any problems.

Once again, thank you.