[Python-checkins] CVS: python/dist/src/Modules _weakref.c,1.9,1.10

Fred L. Drake fdrake@users.sourceforge.net
Fri, 13 Apr 2001 10:15:49 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv13251

Modified Files:
	_weakref.c 
Log Message:
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.


Index: _weakref.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/_weakref.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -r1.9 -r1.10
*** _weakref.c	2001/03/23 06:14:28	1.9
--- _weakref.c	2001/04/13 17:15:47	1.10
***************
*** 741,753 ****
      }
      list = GET_WEAKREFS_LISTPTR(object);
!     while (*list != NULL) {
!         PyWeakReference *current = *list;
!         PyObject *callback = current->wr_callback;
  
!         Py_XINCREF(callback);
!         clear_weakref(current);
!         if (callback != NULL) {
              PyObject *cbresult;
  
              cbresult = PyObject_CallFunction(callback, "O", current);
              if (cbresult == NULL)
--- 741,760 ----
      }
      list = GET_WEAKREFS_LISTPTR(object);
!     /* 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);
  
!         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)
***************
*** 756,759 ****
--- 763,794 ----
                  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);
          }
      }