Kaydet (Commit) 2a5a5ca0 authored tarafından Fred Drake's avatar Fred Drake

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.
üst eb0d9925
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment