cleanup_helper(): Make sure we invalidate all reference objects

before calling any callbacks.  This is important
                   since the callback objects only look at themselves
                   to determine that they are invalide.  This change
                   avoids a segfault when callbacks use a different
                   reference to an object in the process of being
                   deallocated.

This fixes SF bug #415660.
This commit is contained in:
Fred Drake 2001-04-13 17:15:47 +00:00
parent eb0d992520
commit 2a5a5ca012
1 changed files with 41 additions and 6 deletions

View File

@ -740,15 +740,22 @@ cleanup_helper(PyObject *object)
return;
}
list = GET_WEAKREFS_LISTPTR(object);
while (*list != NULL) {
PyWeakReference *current = *list;
PyObject *callback = current->wr_callback;
/* Remove the callback-less basic and proxy references */
if (*list != NULL && (*list)->wr_callback == NULL) {
clear_weakref(*list);
if (*list != NULL && (*list)->wr_callback == NULL)
clear_weakref(*list);
}
if (*list != NULL) {
int count = getweakrefcount(*list);
Py_XINCREF(callback);
clear_weakref(current);
if (callback != NULL) {
if (count == 1) {
PyWeakReference *current = *list;
PyObject *callback = current->wr_callback;
PyObject *cbresult;
Py_INCREF(callback);
clear_weakref(current);
cbresult = PyObject_CallFunction(callback, "O", current);
if (cbresult == NULL)
PyErr_WriteUnraisable(callback);
@ -756,6 +763,34 @@ cleanup_helper(PyObject *object)
Py_DECREF(cbresult);
Py_DECREF(callback);
}
else {
PyObject *tuple = PyTuple_New(count * 2);
PyWeakReference *current = *list;
int i = 0;
for (i = 0; i < count; ++i) {
PyWeakReference *next = current->wr_next;
Py_INCREF(current);
PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
current->wr_callback = NULL;
next = current->wr_next;
clear_weakref(current);
current = next;
}
for (i = 0; i < count; ++i) {
PyObject *current = PyTuple_GET_ITEM(tuple, i * 2);
PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
PyObject *cbresult = PyObject_CallFunction(callback, "O",
current);
if (cbresult == NULL)
PyErr_WriteUnraisable(callback);
else
Py_DECREF(cbresult);
}
Py_DECREF(tuple);
}
}
return;
}