diff --git a/src/common/PythonManager.cpp b/src/common/PythonManager.cpp index 0c7dc4fb..9de6b70a 100644 --- a/src/common/PythonManager.cpp +++ b/src/common/PythonManager.cpp @@ -13,6 +13,12 @@ #include #include +#ifdef CUTTER_ENABLE_PYTHON_BINDINGS +#include +#include +#include +#endif + #include "QtResImporter.h" static PythonManager *uniqueInstance = nullptr; @@ -84,14 +90,57 @@ void PythonManager::initialize() saveThread(); } +#ifdef CUTTER_ENABLE_PYTHON_BINDINGS +static void pySideDestructionVisitor(SbkObject* pyObj, void* data) +{ + void **realData = reinterpret_cast(data); + auto pyQApp = reinterpret_cast(realData[0]); + auto pyQObjectType = reinterpret_cast(realData[1]); + + if (pyObj == pyQApp || !PyObject_TypeCheck(pyObj, pyQObjectType)) { + return; + } + if (!Shiboken::Object::hasOwnership(pyObj) || !Shiboken::Object::isValid(pyObj, false)) { + return; + } + + const char *reprStr = ""; + PyObject *repr = PyObject_Repr(reinterpret_cast(pyObj)); + if (repr) { + reprStr = PyUnicode_AsUTF8(repr); + } + qWarning() << "Warning: QObject from Python remaining (leaked from plugin?):" << reprStr; + if (repr) { + Py_DecRef(repr); + } + + Shiboken::Object::setValidCpp(pyObj, false); + Py_BEGIN_ALLOW_THREADS + Shiboken::callCppDestructor(Shiboken::Object::cppPointer(pyObj, pyQObjectType)); + Py_END_ALLOW_THREADS +}; +#endif + void PythonManager::shutdown() { emit willShutDown(); + restoreThread(); + +#ifdef CUTTER_ENABLE_PYTHON_BINDINGS // This is necessary to prevent a segfault when the CutterCore instance is deleted after the Shiboken::BindingManager Core()->setProperty("_PySideInvalidatePtr", QVariant()); - restoreThread(); + // see PySide::destroyQCoreApplication() + PySide::SignalManager::instance().clear(); + Shiboken::BindingManager& bm = Shiboken::BindingManager::instance(); + SbkObject* pyQApp = bm.retrieveWrapper(QCoreApplication::instance()); + PyTypeObject* pyQObjectType = Shiboken::Conversions::getPythonTypeObject("QObject*"); + void* data[2] = {pyQApp, pyQObjectType}; + bm.visitAllPyObjects(&pySideDestructionVisitor, &data); + + PySide::runCleanupFunctions(); +#endif Py_Finalize();