Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-118199

Flaky tst_QEventLoop::processEvents on QNX

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P2: Important
    • 6.6.1, 6.7.0 FF
    • 6.6.0
    • Core: Event loop
    • None
    • QNX
    • 0cd215853 (dev), c7bc33734 (6.6)

    Description

       Config: Using QtTest library 6.7.0, Qt 6.7.0 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 8.3.0 20190222 (lookup) [qnx710 1535#57]), qnx unknown
       PASS   : tst_QEventLoop::initTestCase()
       FAIL!  : tst_QEventLoop::processEvents() 'eventLoop.processEvents(QEventLoop::WaitForMoreEvents)' returned FALSE. ()
          Loc: [/home/qt/work/qt/qtbase/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp(195)]
       QWARN  : tst_QEventLoop::exec() QEventLoop::exec: instance 0x531e216d40 has already called exec()
      

      QNX in the CI does not build with Glib, so this must be the Unix event dispatcher. There are two ways that QEventDispatcherUNIX::processEvents() can return false:

      bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
      {
          Q_D(QEventDispatcherUNIX);
          d->interrupt.storeRelaxed(0);
      
          // we are awake, broadcast it
          emit awake();
      ...
          if (d->interrupt.loadRelaxed())
              return false;
      ...
          if (include_timers)
              nevents += d->activateTimers();
      
          // return true if we handled events, false otherwise
          return (nevents > 0);
      

      This test should be dispatching one timer:

          // make sure the test doesn't block forever
          int timerId = startTimer(100);
      
          // wait for more events to process, QEventLoop::processEvents()
          // should return true
          aboutToBlockSpy.clear();
          awakeSpy.clear();
          QVERIFY(eventLoop.processEvents(QEventLoop::WaitForMoreEvents));
      

      There should be no other event sources. Debugging into this code shows the dispatcher has exactly two:

      • the threadPipe, which every thread must have
      • this timer

      This dispatcher shouldn't be interrupted because there's no reason why it would be. We unset the flag on entry to this function and there should be nothing connected to the awake() signal, so nothing should interrupt it. There are no other threads running (well, the QtTest watchdog thread, but that won't do anything to us). We'd see it in other OSes too if there were.

      That means we must actually sleep on qt_safe_poll(). Since we do return, I conclude qt_safe_poll() did return. Since we did return, that means one event source must have activated.

      And yet nevents is zero. So conclusion is that QTimerInfoList::activateTimers() did not find the expired timer. That must be a rounding error because of QNX.

      Attachments

        For Gerrit Dashboard: QTBUG-118199
        # Subject Branch Project Status CR V

        Activity

          People

            thiago Thiago Macieira
            thiago Thiago Macieira
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There is 1 open Gerrit change