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

QFileSystemWatcher not safe wrt moveToThread

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Reported
    • Priority: P2: Important
    • Resolution: Unresolved
    • Affects Version/s: 5.15.2
    • Fix Version/s: None
    • Component/s: Core: I/O
    • Labels:
      None
    • Platform/s:
      Windows

      Description

      In a complex application I tried to push the QFileSystemWatcher off the main thread, as it does excessive stat syscalls which can lead to the UI being blocked for a long time when calling addPaths.

      To do that, I basically did this:

      auto watcher = new QFileSystemWatcher;
      watcher->moveToThread(someBackgroundThread);
      // connect to signals, etc.
      // then interact with the normal API via thread safe events:
      QMetaObject::invokeMethod(watcher, [watcher, paths]() {
          watcher->addPaths(path);
      });
      
      // once done with the watcher:
      watcher->deleteLater();
      

      This worked fine on macOS and Linux, but on Windows I started to see strange crashes in our unit tests with this backtrace:

      ucrtbase.dll!abort() Unknown
        vcruntime140.dll!_purecall() Line 29 C++
      > Qt5Core.dll!QAbstractEventDispatcher::filterNativeEvent(const QByteArray & eventType, void * message, long * result) Line 495 C++
        Qt5Core.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 605 C++
        Qt5Core.dll!QCoreApplication::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags, int ms) Line 1316 C++
        Qt5Core.dll!QTest::qWait(int ms) Line 105 C++
        tst_dataset.exe!TestDataset::test_duplicateChannelFileExport() Line 121 C++
      

      I believe this comes from the fact that QFileSystemWatcher is not moveToThread safe:

      
      QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine(QObject *parent)
          : QFileSystemWatcherEngine(parent)
      {
      #ifndef Q_OS_WINRT
          if (QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance()) {
              m_driveListener = new QWindowsRemovableDriveListener(this);
              eventDispatcher->installNativeEventFilter(m_driveListener);
      

      this gets called on construction of the QFileSystemWatcher, but there is no handling of a QEvent::ThreadChange in that class, which should remove the event filter and then re-add it in the new thread.

        Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

            Assignee:
            thiago Thiago Macieira
            Reporter:
            milianw Milian Wolff
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:

                Gerrit Reviews

                There are no open Gerrit changes