Memory leak in QTcpServer attending connections in different thread

295 views Asked by At

I'm developing a RPC server in Qt 4.7 on Windows 7. In order to attend several executions at the same time every request run in a separate thread (as functions might be blocking). I inherited from QTcpServer and reimplemented the incomingConnection function, it looks like this:

void RpcServer::incomingConnection(int socketDescriptor){
    QThread *thread = new QThread();
    RpcServerConnection *client = new RpcServerConnection(socketDescriptor);
    client->moveToThread(thread);    
    connect(thread, SIGNAL(started()), client, SLOT(init()));
    connect(client, SIGNAL(finish()), thread, SLOT(quit()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
}

RpcServerConnection managed data exchange. The init method looks like this:

 void RpcServerConnection::init(){
        qDebug() << "ServerSocket(" << QThread::currentThreadId() << "): Init";
        clientConnection = new QTcpSocket();
        clientConnection->setSocketDescriptor(socketDescriptor);

        connect(clientConnection, SIGNAL(readyRead()), this, SLOT(readFromSocket()));
        connect(clientConnection, SIGNAL(disconnected()), this, SLOT(deleteLater()));
        connect(this, SIGNAL(finish()), this, SLOT(deleteLater()));
    }

Once all data is received and response is sent, finish signal is emited. Debugging I can see that all threads and sockets are deleted. However, process memory increases with every new connection and it is not freed when it ends...

Do I have to free anything else when inheriting from QTcpServer?

1

There are 1 answers

0
Kuba hasn't forgotten Monica On BEST ANSWER

The problem may be with a race/undefined calling order. RpcServerConnection::finish() is connected both to its deleteLater() slot, and to the thread's quit() slot. If the thread's quit slot is entered first, the thread will terminate immediately from the event loop, before anything can be done about the deferred deletion.

Instead of:

connect(client, SIGNAL(finish()), thread, SLOT(quit()));

try:

connect(client, SIGNAL(destroyed()), thread, SLOT(quit()));