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

QDBusPendingCallWatcher::waitForFinished is thread-unsafe

    XMLWordPrintable

Details

    • Bug
    • Resolution: Incomplete
    • P2: Important
    • None
    • 5.15.17, 6.5.0
    • D-Bus
    • None

    Description

      I noticed a TSAN warning on some code using QtDBus (elided for brevity):

       

      WARNING: ThreadSanitizer: data race (pid=3404390)
        Write of size 8 at 0x7b1c000009a0 by thread T1:
          #0 operator delete(void*, unsigned long) <null> (libtsan.so.2+0x8782d)
          #1 QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) <null> (libQt5Core.so.5+0x2a085d)
      
        Previous write of size 8 at 0x7b1c000009a0 by main thread:
          #0 operator new(unsigned long) <null> (libtsan.so.2+0x87f13)
          #1 void doActivate<false>(QObject*, int, void**) <null> (libQt5Core.so.5+0x2d0f36)
      <snip>
          #5 main <null> (xochitl+0x405a2b)
      
        Thread T1 'QDBusConnection' (tid=3404392, running) created by main thread at:
          #0 pthread_create <null> (libtsan.so.2+0x5f0e6)
          #1 QThread::start(QThread::Priority) <null> (libQt5Core.so.5+0xe7fad)
      <snip>
          #5 main <null> (xochitl+0x405a2b) 

      The way I read this, the main thread was trying to post an event (queued emission, or method invoke?), at the same time as QDBusConnection's thread stomped on the QPostEventList by calling QCoreApplication::sendPostedEvents.

       

      Looking at QtDBus, the only place I see this used is in QDBusPendingCallWatcher. Indeed, there are two calls to it in QDBusPendingCallWatcher::waitForFinished, and one of them looks to match up with what I see happening here, on our main thread:

      • We have some code in a generated QDBusAbstractInterface that makes an asyncCallWithArgumentList, and returns a QDBusPendingReply
        • Internally, this moves the watcherHelper to the connection thread (inside QDBusConnectionPrivate::sendWithReplyAsync)
      • We then call QDBusPendingReply::waitForFinished on this reply
        • The call completes
        • QDBusPendingReply then calls sendPostedEvents on the watcherHelper that now lives on the QDBusConnection thread (bad!)
        • Then on the QDBusPendingCallWatcher itself (ok)

      This should be fixed, since I guess it will potentially cause posted events to go missing, or worse...

      Attachments

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

        Activity

          People

            thiago Thiago Macieira
            w00t Robin Burchell
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes