OSDN Git Service

During CatCacheRemoveCList, we must now remove any members that are
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 7 Jan 2006 21:16:10 +0000 (21:16 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 7 Jan 2006 21:16:10 +0000 (21:16 +0000)
dead and have become unreferenced.  Before 8.1, such members were left
for AtEOXact_CatCache() to clean up, but now AtEOXact_CatCache isn't
supposed to have anything to do.  In an assert-enabled build this bug
leads to an assertion failure at transaction end, but in a non-assert
build the dead member is effectively just a small memory leak.
Per report from Jeremy Drake.

src/backend/utils/cache/catcache.c

index 824dbae..6d41ed9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.126 2005/11/22 18:17:24 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.127 2006/01/07 21:16:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -356,7 +356,16 @@ CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
        Assert(ct->my_cache == cache);
 
        if (ct->c_list)
+       {
+               /*
+                * The cleanest way to handle this is to call CatCacheRemoveCList,
+                * which will recurse back to me, and the recursive call will do the
+                * work.  Set the "dead" flag to make sure it does recurse.
+                */
+               ct->dead = true;
                CatCacheRemoveCList(cache, ct->c_list);
+               return;                                 /* nothing left to do */
+       }
 
        /* delink from linked lists */
        DLRemove(&ct->lrulist_elem);
@@ -375,6 +384,8 @@ CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
  *             CatCacheRemoveCList
  *
  * Unlink and delete the given cache list entry
+ *
+ * NB: any dead member entries that become unreferenced are deleted too.
  */
 static void
 CatCacheRemoveCList(CatCache *cache, CatCList *cl)
@@ -391,6 +402,13 @@ CatCacheRemoveCList(CatCache *cache, CatCList *cl)
 
                Assert(ct->c_list == cl);
                ct->c_list = NULL;
+               /* if the member is dead and now has no references, remove it */
+               if (
+#ifndef CATCACHE_FORCE_RELEASE
+                       ct->dead &&
+#endif
+                       ct->refcount == 0)
+                       CatCacheRemoveCTup(cache, ct);
        }
 
        /* delink from linked list */