mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Make sure that when we invoke callback functions associated with weak
references, we do not allow any outstanding exceptions "leak" into the callback's execution state. This closes SF bug #478534.
This commit is contained in:
parent
65760b2173
commit
ef8ebd1e74
1 changed files with 24 additions and 20 deletions
|
@ -655,9 +655,18 @@ PyWeakref_GetObject(PyObject *ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is the implementation of the PyObject_ClearWeakRefs() function; it
|
static void
|
||||||
* is installed in the init_weakref() function. It is called by the
|
handle_callback(PyWeakReference *ref, PyObject *callback)
|
||||||
* tp_dealloc handler to clear weak references.
|
{
|
||||||
|
PyObject *cbresult = PyObject_CallFunction(callback, "O", ref);
|
||||||
|
|
||||||
|
if (cbresult == NULL)
|
||||||
|
PyErr_WriteUnraisable(callback);
|
||||||
|
else
|
||||||
|
Py_DECREF(cbresult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is called by the tp_dealloc handler to clear weak references.
|
||||||
*
|
*
|
||||||
* This iterates through the weak references for 'object' and calls callbacks
|
* This iterates through the weak references for 'object' and calls callbacks
|
||||||
* for those references which have one. It returns when all callbacks have
|
* for those references which have one. It returns when all callbacks have
|
||||||
|
@ -682,25 +691,23 @@ PyObject_ClearWeakRefs(PyObject *object)
|
||||||
clear_weakref(*list);
|
clear_weakref(*list);
|
||||||
}
|
}
|
||||||
if (*list != NULL) {
|
if (*list != NULL) {
|
||||||
int count = _PyWeakref_GetWeakrefCount(*list);
|
PyWeakReference *current = *list;
|
||||||
|
int count = _PyWeakref_GetWeakrefCount(current);
|
||||||
|
int restore_error = PyErr_Occurred() ? 1 : 0;
|
||||||
|
PyObject *err_type, *err_value, *err_tb;
|
||||||
|
|
||||||
|
if (restore_error)
|
||||||
|
PyErr_Fetch(&err_type, &err_value, &err_tb);
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
PyWeakReference *current = *list;
|
|
||||||
PyObject *callback = current->wr_callback;
|
PyObject *callback = current->wr_callback;
|
||||||
PyObject *cbresult;
|
|
||||||
|
|
||||||
Py_INCREF(callback);
|
current->wr_callback = NULL;
|
||||||
clear_weakref(current);
|
clear_weakref(current);
|
||||||
cbresult = PyObject_CallFunction(callback, "O", current);
|
handle_callback(current, callback);
|
||||||
if (cbresult == NULL)
|
|
||||||
PyErr_WriteUnraisable(callback);
|
|
||||||
else
|
|
||||||
Py_DECREF(cbresult);
|
|
||||||
Py_DECREF(callback);
|
Py_DECREF(callback);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyObject *tuple = PyTuple_New(count * 2);
|
PyObject *tuple = PyTuple_New(count * 2);
|
||||||
PyWeakReference *current = *list;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (i = 0; i < count; ++i) {
|
for (i = 0; i < count; ++i) {
|
||||||
|
@ -710,21 +717,18 @@ PyObject_ClearWeakRefs(PyObject *object)
|
||||||
PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
|
PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
|
||||||
PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
|
PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
|
||||||
current->wr_callback = NULL;
|
current->wr_callback = NULL;
|
||||||
next = current->wr_next;
|
|
||||||
clear_weakref(current);
|
clear_weakref(current);
|
||||||
current = next;
|
current = next;
|
||||||
}
|
}
|
||||||
for (i = 0; i < count; ++i) {
|
for (i = 0; i < count; ++i) {
|
||||||
PyObject *current = PyTuple_GET_ITEM(tuple, i * 2);
|
PyObject *current = PyTuple_GET_ITEM(tuple, i * 2);
|
||||||
PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
|
PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
|
||||||
PyObject *cbresult = PyObject_CallFunction(callback, "O",
|
|
||||||
current);
|
handle_callback((PyWeakReference *)current, callback);
|
||||||
if (cbresult == NULL)
|
|
||||||
PyErr_WriteUnraisable(callback);
|
|
||||||
else
|
|
||||||
Py_DECREF(cbresult);
|
|
||||||
}
|
}
|
||||||
Py_DECREF(tuple);
|
Py_DECREF(tuple);
|
||||||
}
|
}
|
||||||
|
if (restore_error)
|
||||||
|
PyErr_Restore(err_type, err_value, err_tb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue