aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2021-01-04 19:10:52 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-01-11 15:48:42 +0000
commitdb9e8e575538c627f9808592e895a9c544d16c4e (patch)
tree2babb8174e5c0a4ca8ffa77a6d15ced161035557
parenta2c4cc01db8d09161349e0ac8489063c2d1383e7 (diff)
allow to use shiboken.delete() to delete Q*Application
This function should initially not allow deleting Q*Application with a shiboken.delete() function, but unfortunately some competitor can do that, so we will as well. Deletion of qApp needs knowledge about qApp. We add a hook function that calls the pyside function `destroyQCoreApplication`. A special problem was testing interactively. See the error description for the days long journey :) Change-Id: I34862425c2cb2cc80d6cafc22d25a867f96f3e0a Fixes: PYSIDE-1470 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> (cherry picked from commit 98aba46414b666c27df3904d2b4313f0a16e05dc) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--sources/pyside6/libpyside/pyside.cpp3
-rw-r--r--sources/pyside6/tests/pysidetest/qapp_like_a_macro_test.py5
-rw-r--r--sources/shiboken6/libshiboken/basewrapper.cpp39
-rw-r--r--sources/shiboken6/libshiboken/basewrapper.h3
-rw-r--r--sources/shiboken6/libshiboken/basewrapper_p.h3
-rw-r--r--sources/shiboken6/libshiboken/sbkstaticstrings.cpp1
-rw-r--r--sources/shiboken6/libshiboken/sbkstaticstrings.h1
7 files changed, 46 insertions, 9 deletions
diff --git a/sources/pyside6/libpyside/pyside.cpp b/sources/pyside6/libpyside/pyside.cpp
index 75b3eb16f..22230703e 100644
--- a/sources/pyside6/libpyside/pyside.cpp
+++ b/sources/pyside6/libpyside/pyside.cpp
@@ -308,6 +308,9 @@ void initQApp()
*/
if (!qApp)
Py_DECREF(MakeQAppWrapper(nullptr));
+
+ // PYSIDE-1470: Register a function to destroy an application from shiboken.
+ setDestroyQApplication(destroyQCoreApplication);
}
PyObject *getMetaDataFromQObject(QObject *cppSelf, PyObject *self, PyObject *name)
diff --git a/sources/pyside6/tests/pysidetest/qapp_like_a_macro_test.py b/sources/pyside6/tests/pysidetest/qapp_like_a_macro_test.py
index 2a796cea8..2233b1b33 100644
--- a/sources/pyside6/tests/pysidetest/qapp_like_a_macro_test.py
+++ b/sources/pyside6/tests/pysidetest/qapp_like_a_macro_test.py
@@ -59,10 +59,11 @@ class qAppMacroTest(unittest.TestCase):
classes = (QtCore.QCoreApplication,
QtGui.QGuiApplication,
QtWidgets.QApplication)
+ fil = sys.stderr
for klass in classes:
- print("created", klass([]))
+ print("CREATED", klass([]), file=fil); fil.flush()
qApp.shutdown()
- print("deleted qApp", qApp)
+ print("DELETED qApp", qApp, file=fil); fil.flush()
# creating without deletion raises:
QtCore.QCoreApplication([])
with self.assertRaises(RuntimeError):
diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp
index 62e2df2cf..7f927523a 100644
--- a/sources/shiboken6/libshiboken/basewrapper.cpp
+++ b/sources/shiboken6/libshiboken/basewrapper.cpp
@@ -95,6 +95,13 @@ static void SbkObjectTypeDealloc(PyObject *pyObj);
static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds);
static SelectableFeatureHook SelectFeatureSet = nullptr;
+static DestroyQAppHook DestroyQApplication = nullptr;
+
+// PYSIDE-1470: Provide a hook to kill an Application from Shiboken.
+void setDestroyQApplication(DestroyQAppHook func)
+{
+ DestroyQApplication = func;
+}
static PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context); // forward
@@ -457,6 +464,12 @@ PyObject *MakeQAppWrapper(PyTypeObject *type)
// object already has a reference from PyObject_GC_New. But this is
// exactly the needed reference that keeps qApp alive from alone!
Py_INCREF(qApp_curr);
+ // PYSIDE-1470: As a side effect, the interactive "_" variable tends to
+ // create reference cycles. It was found when using gc.collect(). But using
+ // PyGC_collect() inside the C code had no effect in the interactive shell.
+ // The cycle exists only in the eval loop of the interpreter!
+ if (PyDict_GetItem(builtins, Shiboken::PyName::underscore()))
+ PyDict_SetItem(builtins, Shiboken::PyName::underscore(), Py_None);
return qApp_curr;
}
@@ -673,7 +686,12 @@ PyObject *SbkObjectTpNew(PyTypeObject *subtype, PyObject *, PyObject *)
PyObject *SbkQAppTpNew(PyTypeObject *subtype, PyObject *, PyObject *)
{
auto self = reinterpret_cast<SbkObject *>(MakeQAppWrapper(subtype));
- return self == nullptr ? nullptr : _setupNew(self, subtype);
+ if (self == nullptr)
+ return nullptr;
+ auto ret = _setupNew(self, subtype);
+ auto priv = self->d;
+ priv->isQAppSingleton = 1;
+ return ret;
}
PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *)
@@ -1154,6 +1172,12 @@ bool wasCreatedByPython(SbkObject *pyObj)
void callCppDestructors(SbkObject *pyObj)
{
+ auto priv = pyObj->d;
+ if (priv->isQAppSingleton && DestroyQApplication) {
+ // PYSIDE-1470: Allow to destroy the application from Shiboken.
+ DestroyQApplication();
+ return;
+ }
PyTypeObject *type = Py_TYPE(pyObj);
SbkObjectTypePrivate *sotp = PepType_SOTP(type);
if (sotp->is_multicpp) {
@@ -1166,18 +1190,19 @@ void callCppDestructors(SbkObject *pyObj)
sotp->cpp_dtor(pyObj->d->cptr[0]);
}
+ if (priv->validCppObject && priv->containsCppWrapper) {
+ BindingManager::instance().releaseWrapper(pyObj);
+ }
+
/* invalidate needs to be called before deleting pointer array because
it needs to delete entries for them from the BindingManager hash table;
also release wrapper explicitly if object contains C++ wrapper because
invalidate doesn't */
invalidate(pyObj);
- if (pyObj->d->validCppObject && pyObj->d->containsCppWrapper) {
- BindingManager::instance().releaseWrapper(pyObj);
- }
- delete[] pyObj->d->cptr;
- pyObj->d->cptr = nullptr;
- pyObj->d->validCppObject = false;
+ delete[] priv->cptr;
+ priv->cptr = nullptr;
+ priv->validCppObject = false;
}
bool hasOwnership(SbkObject *pyObj)
diff --git a/sources/shiboken6/libshiboken/basewrapper.h b/sources/shiboken6/libshiboken/basewrapper.h
index 364f6c5cb..2f0c22e9f 100644
--- a/sources/shiboken6/libshiboken/basewrapper.h
+++ b/sources/shiboken6/libshiboken/basewrapper.h
@@ -106,6 +106,9 @@ LIBSHIBOKEN_API void SbkObjectType_SetReserved(PyTypeObject *type, int value);
LIBSHIBOKEN_API const char **SbkObjectType_GetPropertyStrings(PyTypeObject *type);
LIBSHIBOKEN_API void SbkObjectType_SetPropertyStrings(PyTypeObject *type, const char **strings);
+/// PYSIDE-1470: Set the function to kill a Q*Application.
+typedef void(*DestroyQAppHook)();
+LIBSHIBOKEN_API void setDestroyQApplication(DestroyQAppHook func);
extern LIBSHIBOKEN_API PyTypeObject *SbkObjectType_TypeF(void);
extern LIBSHIBOKEN_API SbkObjectType *SbkObject_TypeF(void);
diff --git a/sources/shiboken6/libshiboken/basewrapper_p.h b/sources/shiboken6/libshiboken/basewrapper_p.h
index 64f7941b7..60fba13c5 100644
--- a/sources/shiboken6/libshiboken/basewrapper_p.h
+++ b/sources/shiboken6/libshiboken/basewrapper_p.h
@@ -97,6 +97,9 @@ struct SbkObjectPrivate
unsigned int validCppObject : 1;
/// Marked as true when the object constructor was called
unsigned int cppObjectCreated : 1;
+ /// PYSIDE-1470: Marked as true if this is the Q*Application singleton.
+ /// This bit allows app deletion from shiboken?.delete() .
+ unsigned int isQAppSingleton : 1;
/// Information about the object parents and children, may be null.
Shiboken::ParentInfo *parentInfo;
/// Manage reference count of objects that are referred to but not owned from.
diff --git a/sources/shiboken6/libshiboken/sbkstaticstrings.cpp b/sources/shiboken6/libshiboken/sbkstaticstrings.cpp
index 35fc2a410..fd34c0eeb 100644
--- a/sources/shiboken6/libshiboken/sbkstaticstrings.cpp
+++ b/sources/shiboken6/libshiboken/sbkstaticstrings.cpp
@@ -61,6 +61,7 @@ STATIC_STRING_IMPL(name, "name")
STATIC_STRING_IMPL(qApp, "qApp")
STATIC_STRING_IMPL(result, "result")
STATIC_STRING_IMPL(select_id, "select_id")
+STATIC_STRING_IMPL(underscore, "_")
STATIC_STRING_IMPL(value, "value")
STATIC_STRING_IMPL(values, "values")
diff --git a/sources/shiboken6/libshiboken/sbkstaticstrings.h b/sources/shiboken6/libshiboken/sbkstaticstrings.h
index d835d286c..4aaef814f 100644
--- a/sources/shiboken6/libshiboken/sbkstaticstrings.h
+++ b/sources/shiboken6/libshiboken/sbkstaticstrings.h
@@ -59,6 +59,7 @@ LIBSHIBOKEN_API PyObject *multi();
LIBSHIBOKEN_API PyObject *name();
LIBSHIBOKEN_API PyObject *result();
LIBSHIBOKEN_API PyObject *select_id();
+LIBSHIBOKEN_API PyObject *underscore();
LIBSHIBOKEN_API PyObject *value();
LIBSHIBOKEN_API PyObject *values();
} // namespace PyName