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

Qt behaviour of deleteLater() triggering another deleteLater() via destroyed() signal

    XMLWordPrintable

Details

    • Bug
    • Resolution: Invalid
    • Not Evaluated
    • None
    • 4.8.0
    • Core: Event loop
    • None
    • i686-pc-linux-gnu; linux-3.1.6, binutils-2.21.1a, gcc-4.6.2, glib-2.14.1, Qt-4.7.4 or Qt-4.8.0, KDE-4.7.4

    Description

      I have a question regarding deleteLater() usage:

      Suppose I have an app which overrides X11EventFilter(), and on reception of some XEvent, does some processing which ends with issuing object_A.deleteLater(). Suppose further that I connect object_A's destroyed() signal to a slot in object_B where I then issue object_B's deleteLater(), or I connect object_A's destroyed() signal to object_B's deleteLater() method/slot directly. What happens then is that if the connection is of type Qt::QueuedConnection, the deferred deletion of object_B is done reasonably quickly when control returns to the event loop, while if the connection is of type Qt::DirectConnection (or simply the default because we've only one thread here), the deferred deletion of object_B is not done until the app is terminated.

      What I'd like to see is for object_B to be deleted from the (main) event loop, reasonably soon after it calls deleteLater() on itself for the default connection type (ie, for either Qt::DirectConnection or Qt::QueuedConnection)

      What I think is happening is that on entry to QApplication::x11ProcessEvent() the (event loop) loopLevel is incremented, lets say to 2, object_A.deleteLater() is issued,
      QApplication::x11ProcessEvent() returns (thus decrementing loopLevel back to 1), and
      then, sometime later from the (main) event loop (just before the deferred deletion of
      object_A is done) object_A emits the destroyed() signal and the connected object_B slot
      is then called under loopLevel 1 (the connection here being direct), thus preventing the deferred object_B deletion until loopLevel 0 is reached, ie, when the app exits.

      My question is if this is intended behaviour, or a bug?

      ADDITIONAL INFO/DISCUSSION:

      Adjust loopLevel for deleteLater() calls triggered by QObject destroyed() signal:

      There exist cases where one connects the destroyed() signal to a slot in which deleteLater() calls are made or triggered. In such cases, as deleteLater() calls are not processed until the (event) loopLevel drops below the current level (which is often (always?) 1 here), the
      deferred deletions may not be done until the application exits. This issue is now occurring in KDE-4.7.X.

      The attached patch addresses this issue by incrementing loopLevel specifically for the 'emit destroyed()' signal in src/corelib/kernel/qobject.cpp.

      I realize this is a bit of a hack, and may not be the proper way to handle this, but hopefully it will spur discussion and resolution of the issue.

      Attachments

        Issue Links

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

          Activity

            People

              earthdomain Earth Domain (Inactive)
              jpsinthemix John Stanley
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes