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

Sporadic crashes when calling deleteLater() on the sender of a signal

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 5.15.10, 6.4.2, 6.4.3
    • Core: Object Model
    • None
    • Statically linked Qt, with OpenSSL 1.1.1w.

    Description

      This issue was discovered in qBittorrent (it is affecting all 4.5.x and the 4.6.0 versions qBittorrent, both qt5 and qt6 builds from 4.5.x, I've tagged a few qt versions in the affected field, but the bug is probably more widespread).

      The relevant piece of code (freeDiskSpaceChecker just emits a signal with the free disk space):

      auto *freeDiskSpaceChecker = new FreeDiskSpaceChecker;
      connect(freeDiskSpaceChecker, &FreeDiskSpaceChecker::checked, this, [this, freeDiskSpaceChecker](const qint64 freeSpaceSize)
      {
          m_freeDiskSpace = freeSpaceSize;
          m_isFreeDiskSpaceCheckerRunning = false;
          m_freeDiskSpaceElapsedTimer.restart();
          freeDiskSpaceChecker->deleteLater();
      });

       

      This randomly (and somewhat rarely) leads to crashes due to nullptr dereference.

      What seems to be happening (based on debug printing added to parts of the qt code) is that doActivate() with freeDiskSpaceChecker as the sender and the QObject::~QObject destructor for the same freeDiskSpaceChecker (triggered by deleteLater() in the slot) are running in parallel threads, leading to the following sequence of events:

      The actual debug logging that was added / the output is detailed in https://github.com/qbittorrent/qBittorrent/issues/19732#issuecomment-1788274402 (sadly adding debug prints to the QObject::~QObject destructor breaks the timing of the issue, the only thing that worked was to add a destructor to the FreeDiskSpaceChecker class and log from there, but we can clearly see that the deleteLater() call and the destructor runs in a separate thread, after the currentConnectionId == 0 check is done, but before the cleanOrphanedConnections() call.

      The issue might be the same as https://bugreports.qt.io/browse/QTBUG-98144

      I haven't tried to create a simplified example of the crash (partly because my experience with qt is close to 0 - I'm only a user of qBittorrent who was affected by this crash and attempted to figure out why they are happening).

      Considering that it is heavily timing related, it would be pretty hard to create a test case that always reproduces (the linked reproduction sometimes took minutes with the binary being bombarded with 10 webAPI calls parallel - in the real world I had 3-4 crashes a week with 60 qBittorrent instances running with moderate webAPI traffic).

      Attachments

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

        Activity

          People

            thiago Thiago Macieira
            aljaspod aljas POD
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes