Skip to content

Commit d45ff9d

Browse files
msmolensjcfr
authored andcommitted
Prevent crashes during and after cleanup
This commit prevents crashes by handling scenarios such as: (a) object destruction after the Python interpreter has been finalized (b) object destruction after cleanup, i.e. the singleton no longer exists Any usage of a Qt enum demonstrates (a). One example that demonstrates (b) is a QTimer object which is created with a QApplication parent. PythonQt::cleanup() is called before the QApplication is completely destroyed, so the code that handles wrapping the QTimer object must handle the case when the PythonQt singleton no longer exists. Co-authored-by: Jean-Christophe Fillion-Robin <[email protected]>
1 parent be34f1b commit d45ff9d

File tree

3 files changed

+11
-9
lines changed

3 files changed

+11
-9
lines changed

src/PythonQt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ class PYTHONQT_EXPORT PythonQt : public QObject {
554554
//@{
555555

556556
//! get access to internal data (should not be used on the public API, but is used by some C functions)
557-
static PythonQtPrivate* priv() { return _self->_p; }
557+
static PythonQtPrivate* priv() { return _self ? _self->_p : NULL; }
558558

559559
//! clear all NotFound entries on all class infos, to ensure that
560560
//! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded

src/PythonQtObjectPtr.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
//----------------------------------------------------------------------------------
4141

4242
#include <PythonQt.h>
43-
43+
4444
#ifndef Py_XSETREF // Some Python2, but not the latest one
4545
#define Py_XSETREF(op1, op2) \
4646
do { \
@@ -109,7 +109,7 @@ PythonQtObjectPtr::PythonQtObjectPtr(PythonQtSafeObjectPtr &&p) :_object(p.takeO
109109

110110
PythonQtObjectPtr::~PythonQtObjectPtr()
111111
{
112-
Py_XDECREF(_object);
112+
if (_object && Py_IsInitialized()) Py_DECREF(_object);
113113
}
114114

115115
void PythonQtObjectPtr::setNewRef(PyObject* o)
@@ -119,7 +119,7 @@ void PythonQtObjectPtr::setNewRef(PyObject* o)
119119
}
120120
}
121121

122-
bool PythonQtObjectPtr::fromVariant(const QVariant& variant)
122+
bool PythonQtObjectPtr::fromVariant(const QVariant& variant)
123123
{
124124
if (!variant.isNull()) {
125125
PyObject* object = nullptr;
@@ -134,7 +134,7 @@ bool PythonQtObjectPtr::fromVariant(const QVariant& variant)
134134
else {
135135
setObject(nullptr);
136136
return false;
137-
}
137+
}
138138
}
139139

140140
QVariant PythonQtObjectPtr::toVariant()

src/PythonQtSignalReceiver.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,12 @@ PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalRecei
178178

179179
PythonQtSignalReceiver::~PythonQtSignalReceiver()
180180
{
181-
// we need the GIL scope here, because the targets keep references to Python objects
182-
PYTHONQT_GIL_SCOPE;
183-
PythonQt::priv()->removeSignalEmitter(_obj);
184-
_targets.clear();
181+
if (PythonQt::priv()) {
182+
// we need the GIL scope here, because the targets keep references to Python objects
183+
PYTHONQT_GIL_SCOPE;
184+
PythonQt::priv()->removeSignalEmitter(_obj);
185+
_targets.clear();
186+
}
185187
}
186188

187189

0 commit comments

Comments
 (0)