Do not call QueuedConnection slot on partialy destroyed object
authorOlivier Goffart <ogoffart@woboq.com>
Thu, 15 Dec 2011 06:24:49 +0000 (07:24 +0100)
committerQt by Nokia <qt-info@nokia.com>
Mon, 19 Dec 2011 13:06:12 +0000 (14:06 +0100)
This is a regression introduced in Qt 4.8
When QApplication::processEvents is called from a destructor, it is
possible that pending events would still be called on the already
destroyed subclass.
Prevent that by using the same pattern as in QMetaObject::activate

Change-Id: Ida50db07ae089264402dafcde7a41a066479d08b
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
src/corelib/kernel/qobject.cpp
tests/auto/corelib/kernel/qobject/tst_qobject.cpp

index 2953225..febe909 100644 (file)
@@ -429,7 +429,7 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
 {
     if (slotObj_) {
         slotObj_->call(object, args_);
-    } else if (callFunction_) {
+    } else if (callFunction_ && method_offset_ <= object->metaObject()->methodOffset()) {
         callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_);
     } else {
         QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_);
index 225e06a..1e69038 100644 (file)
@@ -4101,12 +4101,25 @@ public slots:
     }
 };
 
+static void processEvents()
+{
+    qApp->processEvents();
+}
+
 void tst_QObject::baseDestroyed()
 {
-    BaseDestroyed d;
-    connect(&d, SIGNAL(destroyed()), &d, SLOT(slotUseList()));
-    //When d goes out of scope, slotUseList should not be called as the BaseDestroyed has
-    // already been destroyed while ~QObject emit destroyed
+    {
+        BaseDestroyed d;
+        connect(&d, SIGNAL(destroyed()), &d, SLOT(slotUseList()));
+        //When d goes out of scope, slotUseList should not be called as the BaseDestroyed has
+        // already been destroyed while ~QObject emit destroyed
+    }
+    {
+        BaseDestroyed d;
+        connect(&d, &QObject::destroyed, processEvents);
+        QMetaObject::invokeMethod(&d, "slotUseList", Qt::QueuedConnection);
+        //the destructor will call processEvents, that should not call the slotUseList
+    }
 }
 
 void tst_QObject::pointerConnect()