QTcpSocket and deletion - c++

I'm writing a tcp based server using Qt.
I plan this server to be multithreaded,
so my tcpserver class inherits from QTcpServer and overrides incomingConnection(). Everything is fine, except when it comes to deleting a user.
The TcpServer class manages
a list of QSharedPointer<Client>. When I remove the said client from the list, it gets automatically deleted because of the smart pointer.
My Client class owns a QSharedPointer<QTcpSocket> which means that the client's
QTcpSocket gets deleted when the client is deleted.
Problem is, it seems that Qt tries to use this socket after its deletion, causing Segmentation Fault.
Should I manages a list for the sockets only, and call deleteLater() on them when I dont need them anymore?
Or should I switch my socket's pointer in client class to a normal pointer?
void SlotSocketError(void)
{
QTcpSocket sock = qobject_cast<QTcpSocket *>(QObject::sender());
QSharedPointer<Client> client = GetClientFromSocket(sock);
_clientList.removeAt(GetClientPositionInList(client));
}
QList<QSharedPointer<Client> > _clientsList; // From TcpServer header.
/* Client's class header */
QSharedPointer<QTcpSocket> _socket;

You need to use deleteLater on the Object. Incoming messages may come in after you delete the QTCPSocket. It is documented in Assistant. You can find an example here: qthelp://com.trolltech.qt.472/qdoc/qt4-network.html
M

When you create your QSharedPointers you can pass a deleter to them, so that they'll use deleteLater instead of delete when you remove them from the list.
There is an example that does exactly that in the documentation too:
http://doc.trolltech.com/latest/qsharedpointer.html#QSharedPointer-3

Related

QTcpSocket to QTcpSocket in same object

I am attempting to fake a transfer between two QTcpSockets that happen to be in the same class (which is a googletest fixture). The focus of this is to see if I can send multiple messages between the two and properly extract them again. However, it seems that the two sockets won't connect. Most of the posts I've seen that relate to this don't come up with a working answer, and being as this is definitely not the intended means of use, I'm not sure that there is a simple one.
What I have for setting up the connection:
class TTest : public ::testing::Test, public QObject
{
//Q_OBJECT
protected:
QTcpServer qserv;
QTcpSocket qtcpsock1; //send
QTcpSocket *qtcpsock2; //rcv
TTest() : qserv(this), qtcpsock1(this)
{
while (!qserv.isListening())
{
qserv.listen();
}
qtcpsock1.connectToHost(QHostAddress::LocalHost, qserv.serverPort());
qtcpsock2 = qserv.nextPendingConnection();
qtcpsock1.waitForConnected();
if (!qtcpsock2) std::cout << "socket 2 not initialized\n";
qserv.close();
}
}
Signals/slots currently not in use.
The problem with this is that the event polling loop of the application will not run, so no events will be handled and your function calls will simply not work without it.
In short, the waitForConnected() call will wait for an event that never happens.
The natural solution with Qt is of course to use signals and slots, and let the normal application event loop run.
On a slightly related note: If you want internal communication within the same process consider something other than (heavy and complex) TCP sockets. Simple message queues? Anonymous pipes? Plain strings or arrays?

Can i use QTcpSocket again for another connection after deleteLater?

I try to use QTcpSserver, which would keep connection with one and only one client at a time, until the client disconnects. So, I keep the client with a member pointer in my class.
The problem arises here: In the examples I see on the internet, after disconnected(), it is called deleteLater(). Good, but I would use this class-member pointer again for another connection. Remember that the server keeps one and only one client at a time. So, what if the socket object is deleted after another connection assigned on it?
What I mean is:
class TcpServer(QObject* o) : public QTcpServer {
...
private:
QTcpSocket* client;
}
void TcpServer::connected() {
client = this->nextPendingConnection();
this->pauseAccepting();
connect(client, SIGNAL(disconnected()), client, SLOT(clientDisconnected()));
}
void TcpServer::clientDisconnected() {
client->deleteLater();
this->resumeAccepting();
}
Scenario is this:
Client connected. So, client = nextPendingConnection();
Server paused listening. Does not accept new connection.
Client is disconnected. client needs to be released. So, client->deleteLater() is calleed.
Server continues listening.
New connection comes. So, I need to client = nextPendingConnection();
But, previous client object was deleted? Maybe? Maybe not? What if event loop tries to delete client, after I have assigned the new connection to it in step 5?
So, how would I keep one and only one client, while deleting previous disconnected ones?
Would it be safe if I do this?
void TcpServer::clientDisconnected()
{
QSocket* ptr = client;
ptr->deleteLater();
...
}
I will cite Qt documentation about it:
The object will be deleted when control returns to the event loop.
So deleteLater() is a delayed delete. The object is to be regarded as deleted as soon as the call deleteLater() was made.
Your nextPendingConnection() call will create another object that need to be deleted some time later.
However in your case you only allow one pending connection as you said and disallow accepting until client gets disconnected. I this case it should be safe, in other cases you could overwrite your client pointer and will lose control over it (memory leak).
Even in your case, I would prefer this solution:
void TcpServer::clientDisconnected()
{
if (qobject_cast<QAbstractSocket*>(sender())) {
sender()->deleteLater();
}
...
}
This would also be safe if more than one connection is allowed in future changes of your application.
As i understand nextPendingConnection(); will return pointer to new QTcpSocket class object so you have nothing to worry about.
deleteLater() will scheduled for deletion only your old object. QTcpSocket* client contains only pointer to QTcpSocket class object. When you calling deleteLater() Qt will delete only object to which client was pointed at time of calling this function.

Qt5 QTcpSocket derived class and QTcpServer

I'm developing an application that made sense that I wrapped my classes around the implemented QTcpSocket (since it's a TCP protocol, and I need to be able to use the raw socket and the added features as seemlessly as possible).
So, for the sake of simplicity, my code is structured like this:
class MyTCPSocket : public QTcpSocket
{
Q_OBJECT
// ....
}
class MyTCPServer : public QTcpServer
{
Q_OBJECT
// ....
}
And with QTcpServer, the default nextPendingConnection() function returns an instance of QTcpSocket, which I can't cast up to MyTCPSocket (as far as I'm aware, QTcpSocket doesn't have a copy constructure).
What's my best option for handing this? I was thinking that I could create a new MyTCPSocket and simply set the socket descriptor to the one returned by nextPendingConnection() from MyTCPServer, but I wasn't sure how that would work when the old socket gets deleted.
Is there a better way to handle this situation?
Exactly that: override incomingConnection but don't call the base class, instead create an instance of your QTcpSocket subclass and use setSocketDescriptor on it. If you want to keep QTcpSocket "signal behaviour", also call addPendingConnection and emit newConnection.
Then just downcast the socket you get from nextPendingConnection to your QTcpSocket subclass.

Do we have to delete QUpdSockets?

I'm programming an application that uses QUdpSockets.
As I'm getting memory problems due to creating sockets with the operator new I would like to know if it is necesary to delete them after closing it.
Code below:
socket = new QUdpSocket(this);
socket->bind();
connect(socket, SIGNAL(readyRead()), this, SLOT(getResponse()));
socket->close();
delete socket; //Do I have to do this to free the mem?
Help will be thanked.
Depends on what this is. Whenever that gets destroyed, the QUdpSocket will be too.
As soon as you don't need the socket anymore you can call :
socket->deleteLater();
And yes, it's better to destroy the socket when you don't need it anymore.
An other solution is to delete 'this', so socket will be also deleted.
If your done with the socket you should delete it. This way you are on the safe side. Also it doesnt hurt. However as it was already pointed out "this" will take for the destruction of the socket (see http://doc.qt.io/qt-4.8/qobject.html#QObject ).

ASSERT failure after deleting my qt class on seprate thread

If I have a class FunctionsClass that inherits QObject and has a QTcpServer and QTcpClient in it as member variables. In my main UI class I set up the FunctionsClass member variable on a Qthread called FunctionClassThread by doing:
FunctionsClass *classObj = new FunctionsClass // (classObj is a class member)
classObj->moveToThread( &FunctionClassThread );
FunctionClassThread.start();
// connected some signal/slots..
// do some stuff...
Then I deconstruct the object containing my instance of FunctionsClass by doing:
FunctionClassThread.quit();
FunctionClassThread.wait();
delete classObj; // problem line...........
This error only happens when classObj's QTcpServer is currently listening or itsQTcpSocket is attempting to connect to a server and I delete classObj. The error is: ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread.
Any ideas?
After moving classObj to another thread, you can no longer delete it from the thread you created it in. You either have to delete it within your FunctionsClassThread or move it back to the main thread via code which is processed within the FunctionsClassThread.
Read the Qt docs on moveToThread():
This function can only "push" an object from the current thread to
another thread, it cannot "pull" an object from any arbitrary thread
to the current thread.
So just before your FunctionsClassThread is about to stop, it has to call
classObj->moveToThread( QApplication::thread() );
Of course your FunctionsClassThread needs to be aware of the object, either directly, or by using signals & slots
A QObject has thread affinity. It only likes to be manipulated from the thread it was created in . Use QMetaObject::invokeMethod to invoke a method in context of another thread