From bbf66078ea911cbacca69550da15fa21a000e3ab Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 12 Aug 2011 16:56:39 -0300 Subject: Fix bug 953 - "Segfault when QObject is garbage collected after QTimer.singeShot" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- libpyside/signalmanager.cpp | 13 +++++++++---- tests/QtCore/CMakeLists.txt | 1 + tests/QtCore/bug_953.py | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 tests/QtCore/bug_953.py diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp index b24d0b97e..b7b9b3d93 100644 --- a/libpyside/signalmanager.cpp +++ b/libpyside/signalmanager.cpp @@ -323,11 +323,13 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id, PyObject* pp_name = 0; QMetaProperty mp; PyObject* pySelf = 0; + int methodCount = metaObject->methodCount(); + int propertyCount = metaObject->propertyCount(); if (call != QMetaObject::InvokeMetaMethod) { mp = metaObject->property(id); if (!mp.isValid()) - return id - metaObject->methodCount(); + return id - methodCount; Shiboken::GilState gil; pySelf = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(object); @@ -337,7 +339,7 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id, if (!pp) { qWarning("Invalid property: %s.", mp.name()); Py_XDECREF(pp_name); - return id - metaObject->methodCount(); + return id - methodCount; } } @@ -362,10 +364,13 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id, qWarning("Unsupported meta invocation type."); } + // WARNING Isn't safe to call any metaObject and/or object methods beyond this point + // because the object can be deleted inside the called slot. + if (call == QMetaObject::InvokeMetaMethod) - id = id - metaObject->methodCount(); + id = id - methodCount; else - id = id - metaObject->propertyCount(); + id = id - propertyCount; if (pp || pp_name) { Shiboken::GilState gil; diff --git a/tests/QtCore/CMakeLists.txt b/tests/QtCore/CMakeLists.txt index 9900a85c0..aa646d790 100644 --- a/tests/QtCore/CMakeLists.txt +++ b/tests/QtCore/CMakeLists.txt @@ -20,6 +20,7 @@ PYSIDE_TEST(bug_920.py) PYSIDE_TEST(bug_927.py) PYSIDE_TEST(bug_931.py) PYSIDE_TEST(bug_938.py) +PYSIDE_TEST(bug_953.py) PYSIDE_TEST(blocking_signals_test.py) PYSIDE_TEST(classinfo_test.py) PYSIDE_TEST(child_event_test.py) diff --git a/tests/QtCore/bug_953.py b/tests/QtCore/bug_953.py new file mode 100644 index 000000000..37ef28ea1 --- /dev/null +++ b/tests/QtCore/bug_953.py @@ -0,0 +1,18 @@ +from PySide.QtCore import * + +class Dispatcher(QObject): + _me = None + + def __init__(self): + super(Dispatcher, self).__init__() + self._me = self + QTimer.singleShot(0, self._finish) + + def _finish(self): + del self._me # It can't crash here! + QTimer.singleShot(10, QCoreApplication.instance().quit) + +if __name__ == '__main__': + app = QCoreApplication([]) + Dispatcher() + app.exec_() -- cgit v1.2.3