Python - Save and restore exception state before calling destroy.
PyObject_CallFunction has the potential to silently drop the active exception. In cases where the user just finished iterating a generator, StopIteration will be active. Most of the time this is fine because destroy() won't raise an exception. On Python 3 however, and with a debug interpreter, you will get an assertion failure inside of Python. And in the worst case scenario, if destroy() does throw an exception, the intepreter probably won't be able to correctly detect the end of the iteration.
This commit is contained in:
parent
00ca9c07d1
commit
2fa9454c9f
1 changed files with 14 additions and 7 deletions
|
|
@ -537,14 +537,21 @@ SwigPyObject_dealloc(PyObject *v)
|
|||
/* destroy is always a VARARGS method */
|
||||
PyObject *res;
|
||||
if (data->delargs) {
|
||||
/* we need to create a temporary object to carry the destroy operation */
|
||||
PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
|
||||
res = SWIG_Python_CallFunctor(destroy, tmp);
|
||||
Py_DECREF(tmp);
|
||||
/* we need to create a temporary object to carry the destroy operation */
|
||||
PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
|
||||
/* PyObject_CallFunction() has the potential to silently drop the active
|
||||
active exception. In cases where we just finished iterating over a
|
||||
generator StopIteration will be active right now, and this needs to
|
||||
remain true upon return from SwigPyObject_dealloc. So save and restore. */
|
||||
PyObject *val = NULL, *type = NULL, *tb = NULL;
|
||||
PyErr_Fetch(&val, &type, &tb);
|
||||
res = SWIG_Python_CallFunctor(destroy, tmp);
|
||||
PyErr_Restore(val, type, tb);
|
||||
Py_DECREF(tmp);
|
||||
} else {
|
||||
PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
|
||||
PyObject *mself = PyCFunction_GET_SELF(destroy);
|
||||
res = ((*meth)(mself, v));
|
||||
PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
|
||||
PyObject *mself = PyCFunction_GET_SELF(destroy);
|
||||
res = ((*meth)(mself, v));
|
||||
}
|
||||
Py_XDECREF(res);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue