summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2011-08-12 16:56:39 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2011-08-12 18:28:44 -0300
commitb261ff4642d4c4cc7e33862c3ea1477e3e6d89fc (patch)
treea3c7bdabaa16eb3162425ed781e925aa05d7f7d6
parent01b90a3a587d6afd9ec4bf3d6ad2ea83a9548b6d (diff)
downloadpyside-b261ff4642d4c4cc7e33862c3ea1477e3e6d89fc.tar.gz
pyside-b261ff4642d4c4cc7e33862c3ea1477e3e6d89fc.tar.xz
pyside-b261ff4642d4c4cc7e33862c3ea1477e3e6d89fc.zip
Fix bug 953 - "Segfault when QObject is garbage collected after QTimer.singeShot"
Reviewer: Renato Ara├║jo <renato.filho@openbossa.org> Luciano Wolf <luciano.wolf@openbossa.org>
-rw-r--r--libpyside/signalmanager.cpp13
-rw-r--r--tests/QtCore/CMakeLists.txt1
-rw-r--r--tests/QtCore/bug_953.py18
3 files changed, 28 insertions, 4 deletions
diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp
index b24d0b9..b7b9b3d 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 9900a85..aa646d7 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 0000000..37ef28e
--- /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_()