From 7eb5428199fddf69b24e03c85db3e8873cde605d Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 7 Jan 2006 21:16:10 +0000 Subject: [PATCH] During CatCacheRemoveCList, we must now remove any members that are 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 | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 824dbaed02f..6d41ed94525 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -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 */ -- GitLab