QThread & Lost Queued-Signals



  • Hello everyone,

    I have the situation, that somehow signals from a different thread are lost, and I'm unsure why that is the case.

    The situation:
    I have a class SslSocket that is only depending on QObject

    class SslSocket : public QObject
    {
        Q_OBJECT
    
    public:
        SslSocket(QString host, int port, SmtpClient::ConnectionType connection);
        ~SslSocket();
    
        enum errorType{
            connectError,
            loginError,
            sendError
        };
        Q_ENUM(errorType)
    ...
    ...
    }
    

    In it, I'm using the asynchronus QSslSocket approch to communicate with a server. Even so I use readyRead and bytesWritten instead of the blocking functions I decided to wrap the class up in a seperated thread.

        SslSocket *smtp = new SslSocket("smtp.gmail.com",465,SmtpClient::SslConnection);
        QThread *t = new QThread();
        smtp->moveToThread(t);
    
        connect(t, &QThread::started,   smtp, &SslSocket::initSslSocket);
        connect(t, &QThread::finished,  smtp, &SslSocket::deleteLater);
        connect(t, &QThread::finished,  t,    &QThread::deleteLater);
    
        connect(this, &SmtpEmail::destroyed, t, &QThread::quit);
        connect(smtp, &SslSocket::errorMsg,         this, &SmtpEmail::errorManagement/*,Qt::DirectConnection*/); //<= Problem
    ...
    ...
    t->start();
    

    It is working as indetend, but while testing for potential Errors, I set the server to refuse the SSL-Handshake.
    Using qDebug I see that the SIGNAL errorMsg is emitted, but the SLOT errorManagement is not called, ever.

    But when I change the connection type from Qt::QueuedConnection to Qt::DirectConnection, the slot is called! The slot is also called, when I do not move smtp to the thread, but let it life in the main thread.

    Because the object lifes in a different thread I rather would not use DirectConnection if I can avoid it.

    So, anyone any idea what is going on ?

    Thanks



  • This looks like a typical case in which you don't have an event loop running or the event loop in the main thread is blocked (stuck in a while(true) or something similar)



  • @VRonin hi,

    I'm quite sure that I'have a event loop and that it is running. I do call QThread::start() , queded-connections inside the threaded class are executed without problem as well. Also QThread::isrunning() returns true:

    I added the following to test:

    QTimer *timer = new QTimer();
        timer->setInterval(500);
        connect(timer, &QTimer::timeout, timer, [=]{
            qDebug() << "Thread"<< QTime::currentTime().toString("ss.zzz"); 
            emit errorMsg(QTime::currentTime().toString("ss.zzz"));
        });
        timer->start();
    
    connect(smtp, &SslSocket::errorMsg,         this, &SmtpEmail::errorManagement);
    connect(smtp, &SslSocket::errorMsg, smtp,[=](QString s){qDebug()<< "Queued:"<< s;},Qt::QueuedConnection );
        connect(smtp, &SslSocket::errorMsg, smtp,[=](QString s){qDebug()<< "Direct:"<< s;},Qt::DirectConnection );
    connect(smtp, &SslSocket::errorMsg, this, &SmtpEmail::msg, Qt::QueuedConnection);
        connect(smtp, &SslSocket::errorMsg, this, &SmtpEmail::msg, Qt::DirectConnection);
    
    void SmtpEmail::msg(QString s)
    {
        qDebug() << "Slot"<< s;
    }
    

    the result is:

    Thread "14.433"
    Direct: "14.433"
    Slot "14.433"
    Queued: "14.433"
    

    The queued connections, except the lambda one, are missing. And I'm not sure you can actually queue lambdas!?

    ...

    I don't think I blocked the main thread.

    • I don't use while loops in my main thread. Howerver there is one in the SslSocket class that I use to read the data, but it should not becalled before the readyread signal
    if(socket->canReadLine()){
            while (socket->canReadLine())
            ...
    }
    
    • I can resize the window without a problem
    • I do get information from my other worker thread, that is using a serialport


  • OK, just made a clean project with this code:

        QTimer *timer = new QTimer();
        QThread *thread = new QThread();
        timer->moveToThread(thread);
        timer->setInterval(500);
        connect(timer, &QTimer::timeout, this, &MainWindow::mySlot);
        connect(thread, &QThread::started, timer, QOverload<>::of(&QTimer::start));
        thread->start();
    
    void MainWindow::mySlot()
    {
        qDebug() << "my Slot"<< QTime::currentTime().toString("mm.zzz");
    }
    

    It is calling the slot, like it should. If I copy and paste that one to my class where I have the problems, and adjust mySlot,

    the slot is not called....

    I'll have to look into it more. I defenitly messed up somewhere...



  • could you post the code of SmtpEmail?



  • @VRonin

    I have the code here, I took the liberty to obscure some strings and add sslsocket as well.



  • I'm an Idiot.

    I overwrote QWidget::event to emit a signal in certain situations.

    bool SmtpEmail::event(QEvent *e)
    {
        if(e->type() == QEvent::MouseButtonPress ||
                e->type() == QEvent::MouseButtonRelease ||
                e->type() == QEvent::MouseMove ){
            QMouseEvent *ev =(QMouseEvent *)e;
            emit mouseEvent(ev->type(),mapToGlobal(ev->pos()));
        }
        return false;
    }
    

    what I should have written:

    bool SmtpEmail::event(QEvent *e)
    {
        if(e->type() == QEvent::MouseButtonPress ||
                e->type() == QEvent::MouseButtonRelease ||
                e->type() == QEvent::MouseMove ){
            QMouseEvent *ev =(QMouseEvent *)e;
            emit mouseEvent(ev->type(),mapToGlobal(ev->pos()));
        }
        return QFrame::event(e);
    }
    

    returning false als the default value aparently interrupt the QueuedConnection mechanic.


Log in to reply
 

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