mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 09:30:44 +00:00
Fix C++ invokes being responsible for destroying python callbacks
* If the last refcount on a python lambda/temp function is released when a wrapping std::function is destroyed in a C++ invoke, we can't destroy it safely. Instead we queue up that decref and process it the next chance we're able (which is either when the current execution finishes for a python shell execution, or on the next function call which handles extensions).
This commit is contained in:
@@ -137,6 +137,10 @@ QMap<rdcstr, PyObject *> PythonContext::extensions;
|
||||
|
||||
static PyObject *current_global_handle = NULL;
|
||||
|
||||
static QMutex decrefQueueMutex;
|
||||
static QList<PyObject *> decrefQueue;
|
||||
extern "C" void ProcessDecRefQueue();
|
||||
|
||||
void FetchException(QString &typeStr, QString &valueStr, int &finalLine, QList<QString> &frames)
|
||||
{
|
||||
PyObject *exObj = NULL, *valueObj = NULL, *tracebackObj = NULL;
|
||||
@@ -845,6 +849,8 @@ void PythonContext::executeString(const QString &filename, const QString &source
|
||||
|
||||
PyEval_SetTrace(NULL, NULL);
|
||||
|
||||
ProcessDecRefQueue();
|
||||
|
||||
Py_XDECREF(thisobj);
|
||||
Py_XDECREF(traceContext);
|
||||
}
|
||||
@@ -1327,6 +1333,26 @@ extern "C" void SetThreadBlocking(PyObject *global_handle, bool block)
|
||||
redirector->block = block;
|
||||
}
|
||||
|
||||
extern "C" void QueueDecRef(PyObject *obj)
|
||||
{
|
||||
QMutexLocker lock(&decrefQueueMutex);
|
||||
|
||||
decrefQueue.push_back(obj);
|
||||
}
|
||||
|
||||
extern "C" void ProcessDecRefQueue()
|
||||
{
|
||||
QMutexLocker lock(&decrefQueueMutex);
|
||||
|
||||
if(decrefQueue.isEmpty())
|
||||
return;
|
||||
|
||||
for(PyObject *obj : decrefQueue)
|
||||
Py_XDECREF(obj);
|
||||
|
||||
decrefQueue.clear();
|
||||
}
|
||||
|
||||
extern "C" QWidget *QWidgetFromPy(PyObject *widget)
|
||||
{
|
||||
return PythonContext::QWidgetFromPy(widget);
|
||||
|
||||
Reference in New Issue
Block a user