Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Randomly Occuring assertion error



  • Hello everybody,

    I'm pretty new to qt and currently facing some strange behaviour of my program I can't explain to my self.
    The purpose of my code is to interface two sensor devices and forward the obtained information to a control loop. This is why i chose threads.

    Like every second time I run my the code (without compiling in the mean time), I get this error:
    ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x8501bb0. Receiver '' (of type 'QTimer') was created in thread 0x0x8670578", file kernel\qcoreapplication.cpp, line 576

    The code where all threads are defined and stuff looks like this:

        m_CommThread = new CCommRunnable(IpHandDevice,DeviceType::Hand);
        qDebug()<<"m_CommThread:"<<m_CommThread->thread();
        m_CommTimer = new QTimer();
        qDebug()<<"m_CommTimer"<<m_CommTimer->thread();
    
    
    
       m_CommThreadHead = new CCommRunnable(IpHeadDevice,DeviceType::Head);
       qDebug()<<"m_CommThreadHead"<<m_CommThreadHead->thread();
       m_CommHeadTimer = new QTimer();
       qDebug()<<"m_CommHeadTimer"<<m_CommHeadTimer->thread();
    
        m_ControlThread = new CControlRunnable();
        qDebug()<<"m_ControlThread"<<m_ControlThread->thread();
        m_ControlTimer = new QTimer();
        qDebug()<<"m_ControlTimer"<<m_ControlTimer->thread();
    
        m_CommTimer->setInterval(m_CommPeriod);
        m_CommHeadTimer->setInterval(m_CommPeriod);
        m_ControlTimer->setInterval(m_ControlPeriod);
    
        QObject::connect(m_CommTimer, &QTimer::timeout,m_CommThread,&CCommRunnable::onTimeOut);
        QObject::connect(m_CommHeadTimer, &QTimer::timeout,m_CommThreadHead,&CCommRunnable::onTimeOut);
        QObject::connect(m_ControlTimer, &QTimer::timeout,m_ControlThread,&CControlRunnable::onTimeOut);
    
        QObject::connect(m_CommThread, &CCommRunnable::sigNewValues,m_ControlThread,&CControlRunnable::sltOnNewValues);
    
        QThreadPool::globalInstance()->start(m_CommThread,0);
        QThreadPool::globalInstance()->start(m_CommThreadHead,0);
        QThreadPool::globalInstance()->start(m_ControlThread,0);
    
        m_CommTimer->start();
        m_CommHeadTimer->start();
        m_ControlTimer->start();
    

    Could someone explain this behaviour to me? I'd be glad to fix the error but also to get a understanding where it's coming from.

    Cheers,
    Chris



  • Hi,
    Try to add a paramater Qt::QueuedConnection at all QObject::connect as below.

    QObject::connect(m_CommTimer, &QTimer::timeout,m_CommThread,&CCommRunnable::onTimeOut,  Qt::QueuedConnection );
    QObject::connect(m_CommHeadTimer, &QTimer::timeout,m_CommThreadHead,&CCommRunnable::onTimeOut, Qt::QueuedConnection );
    QObject::connect(m_ControlTimer, &QTimer::timeout,m_ControlThread,&CControlRunnable::onTimeOut, Qt::QueuedConnection );
    

    sendEvent works directly. PostEvent sends messages to Qt Message Queue.



  • Thanks for the switft response, sadly it didn't fix the problem.

    I'm wondering if there are any background processes which are the cause of this problem.
    In my code I've never created a connection with the a QTimer as a reciever, but the error message points out that a qtimer is the reciever of this failing message. Current thread 0x0x8501bb0. Receiver '' (of type 'QTimer') was created in thread 0x0x8670578


  • Lifetime Qt Champion

    Hi @ChrisWeiter, welcome.

    You should read https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation if you really need threads for your task (which I doubt).

    Regards



  • @ChrisWeiter

    It seems also QObject::connect is in the wrong place. I am not sure also your Runnables is correct. QObject::connect should be placed after the "QThreadPool::globalInstance()->start(m_ControlThread,0);". All of your Runnable slots should connect a worker class that should be created in your Runnable::run method and Runnable::run method should end an exec() to start event queue.

    Can you send your Runnable class. May be I can help correctly.


  • Moderators

    @CKurdu said in Randomly Occuring assertion error:

    Try to add a paramater Qt::QueuedConnection at all QObject::connect as below.

    Doing this semi-randomly is really bad advice. If a program doesn't work with auto connections it's a safe bet forcing queued isn't going to fix it. At best it's going to hide some problem.

    @ChrisWeiter said in Randomly Occuring assertion error:

    Could someone explain this behaviour to me?

    Not without enough information. For one what does the stack trace show? For two what are those classes that are being run in separate threads, and have you made sure they don't touch non-reentrant/non-thread-safe data?

    Also don't use threads if you don't need them (not clear here if you do or don't), you'll spare yourself a lot of headaches.



  • @CKurdu said in Randomly Occuring assertion error:

    @ChrisWeiter

    It seems also QObject::connect is in the wrong place. I am not sure also your Runnables is correct. QObject::connect should be placed after the "QThreadPool::globalInstance()->start(m_ControlThread,0);". All of your Runnable slots should connect a worker class that should be created in your Runnable::run method and Runnable::run method should end an exec() to start event queue.

    Can you send your Runnable class. May be I can help correctly.

    Thanks CKurdu. With your hints I was able to fix it.
    Because I ran into some difficulties earlier, I moved all the code from the run to the constructor.
    The solution was to initialize the worker in the constructor, but do the connections in the run().

    Below the working code.

    CCommRunnable::CCommRunnable(QString DeviceIp, DeviceType DeviceTypeIndicator)
    {
        WorkerDataCollector = new CDataCollector(DeviceIp);
    }
    
    void CCommRunnable::run()
    {
        QObject::connect(this,&CBasisRunnable::sigDoWork,WorkerDataCollector,
            &CDataCollector::onDoWork,Qt::QueuedConnection);
       QObject::connect(WorkerDataCollector,&CDataCollector::sigNewData,this,
        &CCommRunnable::sltonValuesChanged,Qt::QueuedConnection);
    
        m_EventLoop.exec(QEventLoop::AllEvents);
    }
    

    @kshegunov considering your comment on the connection, I'm going to remove the parameter.
    @aha_1980 why do you doubt I need threads? I'm not eager to use them, but as I interface the sensors via a socket connection it seemed best to me, to make the different parts of my code independent from the responsiveness of the connection. And probably there will be added more stuff to interface in the future.


  • Lifetime Qt Champion

    @ChrisWeiter said in Randomly Occuring assertion error:

    @aha_1980 why do you doubt I need threads? I'm not eager to use them, but as I interface the sensors via a socket connection

    E.g. because Qt provides an asynchronous API for sockets already. No need for threads.

    Regards



  • @ChrisWeiter

    I am sorry. It seems you have the wrong usage. You should create your worker in the run method.
    You should read the link that @aha_1980 has been sent more carefully.



  • @ChrisWeiter
    hi,
    Look at this link that I created for you. Build and run and look at thread's output. You will see all threads different. Then move line 17 into line 12 in RunnableOne.cpp then build and run. You will see all threads same.

    Look at Thread Affinity for more information.

    I don't know you really need threads. If you have long progress before sending a message to a socket, you can do it with threads.
    Also, I am not sure that my example is proper for your needs because I created from your code structure. It needs more stabilizations.

    I am warning you, threads really create unexpectable results. I hope I helped you.


Log in to reply