? diff
? diff2
Index: cPickleCache.c
===================================================================
RCS file: /cvs-repository/Zope/lib/python/ZODB/Attic/cPickleCache.c,v
retrieving revision 1.68.10.3
diff -c -4 -r1.68.10.3 cPickleCache.c
*** cPickleCache.c	30 Apr 2003 17:03:34 -0000	1.68.10.3
--- cPickleCache.c	27 Jan 2004 23:02:06 -0000
***************
*** 216,224 ****
  #endif
  
  
  static int
! scan_gc_items(ccobject *self,int target)
  {
      /* This function must only be called with the ring lock held,
         because it places a non-object placeholder in the ring.
      */
--- 216,224 ----
  #endif
  
  
  static int
! scan_gc_items(ccobject *self,int target,CPersistentRing *terminal)
  {
      /* This function must only be called with the ring lock held,
         because it places a non-object placeholder in the ring.
      */
***************
*** 265,281 ****
              return -1;
          }
  #endif
  
! 	/* back to the home position. stop looking */
!         if (here == &self->ring_home)
!             return 0;
  
          /* At this point we know that the ring only contains nodes
! 	   from persistent objects, plus our own home node. We know
! 	   this because the ring lock is held.  We can safely assume
! 	   the current ring node is a persistent object now we know it
! 	   is not the home */
          object = OBJECT_FROM_RING(self, here, "scan_gc_items");
          if (!object) 
  	    return -1;
  
--- 265,288 ----
              return -1;
          }
  #endif
  
!         /* reached the end position. stop looking */
!         if (here == terminal)
!               return 0;
! 
!         /* back to the home position. should not happen */
!         if (here == &self->ring_home) {
!             PyErr_SetString(PyExc_RuntimeError,
!                   "reached home before terminal, in scan_gc_items");
!             return -1;
!         }
  
          /* At this point we know that the ring only contains nodes
! 	   from persistent objects, plus our own home node, plus the
!            terminal node. We know this because the ring lock is held.
!            We can safely assume the current ring node is a persistent
!            object now. */
          object = OBJECT_FROM_RING(self, here, "scan_gc_items");
          if (!object) 
  	    return -1;
  
***************
*** 325,332 ****
--- 332,343 ----
  
  static PyObject *
  lockgc(ccobject *self, int target_size)
  {
+     int error;
+     CPersistentRing terminal;
+ 
+ 
      /* This is thread-safe because of the GIL, and there's nothing
       * in between checking the ring_lock and acquiring it that calls back
       * into Python.
       */
***************
*** 338,350 ****
      if (IS_RING_CORRUPT(self, "pre-gc")) 
  	return NULL;
      ENGINE_NOISE("<");
      self->ring_lock = 1;
!     if (scan_gc_items(self, target_size)) {
!         self->ring_lock = 0;
!         return NULL;
!     }
      self->ring_lock = 0;
      ENGINE_NOISE(">\n");
      if (IS_RING_CORRUPT(self, "post-gc")) 
  	return NULL;
  
--- 349,376 ----
      if (IS_RING_CORRUPT(self, "pre-gc")) 
  	return NULL;
      ENGINE_NOISE("<");
      self->ring_lock = 1;
! 
!     /* insert a placeholder just before the head node. This will be used to
!      * terminate the scan_gc_items loop. Items touched during the
!      * deactivation run will get inserted between the head and this terminal
!      * node, and will not get re-scanned. */
!     terminal.next = &self->ring_home;
!     terminal.prev = self->ring_home.prev;
!     self->ring_home.prev->next = &terminal;
!     self->ring_home.prev = &terminal;
! 
!     error = scan_gc_items(self, target_size, &terminal);
! 
!     /* unlink the placeholder from the ring */
!     terminal.next->prev = terminal.prev;
!     terminal.prev->next = terminal.next;
! 
      self->ring_lock = 0;
+     if (error)
+         return NULL;
+ 
      ENGINE_NOISE(">\n");
      if (IS_RING_CORRUPT(self, "post-gc")) 
  	return NULL;
  
