Search code examples
qtlambdaqlocalsocket

QLocalSocket - QTimer and Lambda


I have a strange behavior with Lambda and timer on Qt 5.7.1. Probably a mistake from me.

I start a connection with a socket and set a timer to check whether it was connected or not after a certain amount of time.

The signal connected of the socket will stop the time.

However, with the following implementation, the timer does not stop even if the connected signal is called.

constructor:

m_connectTimeout.setInterval(5000);

connect(&m_socket, &QLocalSocket::connected, [&]()
{
    // this is called first and should stop the timer.
    m_connectTimeout.stop();
});


connect(&m_connectTimeout, &QTimer::timeout, [&](){
       // this is still called
});

Here is a minimum example with problem reproducible on Qt5.7.1 and Windows 10.

#include <QtCore>
#include <QtNetwork>

#define PIPENAME "testbug"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QTimer timer;
    QLocalSocket socketClient, *socketServer;
    QLocalServer server;
    timer.setInterval(2000);


    QObject::connect(&timer, &QTimer::timeout, [&]
    {
        qDebug() << "client connection timed out";
        timer.stop();
    });

    QObject::connect(&socketClient, &QLocalSocket::connected, [&]
    {
        qDebug() << "client connected";
        timer.stop();
    });

    QObject::connect(&server, &QLocalServer::newConnection, [&]
    {
        qDebug() << "server got connection";
        socketServer = server.nextPendingConnection();
    });

    server.setSocketOptions(QLocalServer::WorldAccessOption);
    server.listen(PIPENAME);

    qDebug() << "client connecting. . .";
    socketClient.connectToServer(PIPENAME, QLocalSocket::ReadWrite);
    timer.start();

    return a.exec();
}

Output of the program:

client connecting. . .
client connected
server got connection
client connection timed out

I also noticed it's not always reproducible and seems somehow random.


Solution

  • Actually it seems the code works, it's just that the connection is so fast, that the timer.stop is called before the timer.start.

    Starting the timer before calling connect to server seems to solve the issue

    m_timer.start();
    m_socketClient.connectToServer(PIPENAME, QLocalSocket::ReadWrite);
    

    This would mean that connectToServer does some calls on the event loop in the background, allowing the slots to be called, even before the next line is executed.