Mercurial > cpython-lru_cache-weakref
diff Modules/_weakref.c @ 17497:6a3776201750 legacy-trunk
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.
| author | Fred Drake <fdrake@acm.org> |
|---|---|
| date | Fri, 13 Apr 2001 17:15:47 +0000 |
| parents | 8df0f65e3860 |
| children | 8d9eb5a4ebcd |
line wrap: on
line diff
--- a/Modules/_weakref.c Fri Apr 13 17:08:15 2001 +0000 +++ b/Modules/_weakref.c Fri Apr 13 17:15:47 2001 +0000 @@ -740,15 +740,22 @@ 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 @@ 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; }
