QTcpSocket does not detect disconnect when created from worker thread



  • I am trying to use a QTcpSocket from a worker thread like in this example http://doc.qt.io/qt-5/qtnetwork-blockingfortuneclient-example.html

    The socket connects properly.

    However it fails to detects when the host disconnects. So the thread remains stuck in the loop.

    If i create the socket in the main thread, it detects the disconnection properly.

    class ClientThread : public QThread
    {
    Q_OBJECT

    public:
        ClientThread(QObject *parent = 0) {};
        ~ClientThread() {};
    
        void run() Q_DECL_OVERRIDE;
    

    };

    void ClientThread::run()
    {
    QTcpSocket socket;
    socket.connectToHost(SERVER, PORT);

    if (socket.waitForConnected(TIMEOUT)) 
    {
        // sleep as long as connected
        while(socket.state() == QAbstractSocket::SocketState::ConnectedState)
        {
            QThread::msleep(10);
        }
    
        // should exit here when host disconnects
        QThread::msleep(10);
    }
    

    }

    // from Main thread I call this
    client_thread.start();

    Why is that?


  • Moderators

    @Milo
    Did you check if it detects the dsiconnect when in main thread?

    AFAIK there might be a long timeout until the state is changed. I am checking the write to the host does not send all data respectively no data.



  • Yes I did.

    if I run the following on the main thread, I exit the loop right when I close the server.

    QTcpSocket socket;
    socket.connectToHost(SERVER, PORT);

    if (socket.waitForConnected(TIMEOUT))
    {
    // sleep as long as connected
    while(socket.state() == QAbstractSocket::SocketState::ConnectedState)
    {
    QThread::msleep(10);
    }

    // should exit here when host disconnects
    QThread::msleep(10);
    

    }

    }



  • from client_thread.start(); I see the thread is created on the stack, are you sure it does not go out of scope? QThread::start does not block the main thread.

    Could you show us the method where you call start() or try making client_thread a pointer to ClientThread and do

    client_thread=new ClientThread;
    connect(client_thread,&ClientThread::finished,client_thread,&ClientThread::deleteLater);
    client_thread->start();
    

    P.S.
    When reimplementing any QObject you should always call the base class constructor to avoid breaking Qt parent-child system
    ClientThread(QObject *parent = 0) {};
    should become
    ClientThread(QObject *parent = 0) :QThread(parent){};



  • sure @VRonin

    client_thread is a member of a class deriving from QDialog.
    I call client_thread.start() start from a button slot.


  • Qt Champions 2016

    @Milo
    This code can't work simply because events are not processed for the thread. This means all QSocketNotifiers are stuck and the state can't be changed because of the endless loop. Change that or use the async API.

    @VRonin
    Additional implication of the above is that you can't have signals emitted from other threads execute slots in the current (when connected with Qt::QueuedConnection/Qt::AutoConnection/Qt::BlockingQueuedConnection).


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.