From 08890b407e976e4871f2024ed5a3071d0fa510a6 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 25 Mar 2005 18:30:28 +0000
Subject: [PATCH] Fix resource owner code to generate catcache and relcache
 leak warnings when open references remain during normal cleanup of a resource
 owner. This restores the system's ability to warn about leaks to what it was
 before 8.0.  Not really a user-level bug, but helpful for development.

---
 src/backend/utils/cache/catcache.c    | 39 ++++++++++++++++++++++-----
 src/backend/utils/resowner/resowner.c | 25 ++++++++++++++++-
 src/include/utils/catcache.h          |  5 +++-
 3 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 68995f98388..44ef1de6eee 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.118 2004/12/31 22:01:25 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.119 2005/03/25 18:30:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -556,8 +556,7 @@ AtEOXact_CatCache(bool isCommit)
 			if (cl->refcount != 0)
 			{
 				if (isCommit)
-					elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
-						 ccp->cc_relname, ccp->id, cl, cl->refcount);
+					PrintCatCacheListLeakWarning(cl);
 				cl->refcount = 0;
 			}
 
@@ -579,10 +578,7 @@ AtEOXact_CatCache(bool isCommit)
 		if (ct->refcount != 0)
 		{
 			if (isCommit)
-				elog(WARNING, "cache reference leak: cache %s (%d), tuple %u has count %d",
-					 ct->my_cache->cc_relname, ct->my_cache->id,
-					 HeapTupleGetOid(&ct->tuple),
-					 ct->refcount);
+				PrintCatCacheLeakWarning(&ct->tuple);
 			ct->refcount = 0;
 		}
 
@@ -1807,3 +1803,32 @@ PrepareToInvalidateCacheTuple(Relation relation,
 					 ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId);
 	}
 }
+
+
+/*
+ * Subroutines for warning about reference leaks.  These are exported so
+ * that resowner.c can call them.
+ */
+void
+PrintCatCacheLeakWarning(HeapTuple tuple)
+{
+	CatCTup    *ct = (CatCTup *) (((char *) tuple) -
+								  offsetof(CatCTup, tuple));
+
+	/* Safety check to ensure we were handed a cache entry */
+	Assert(ct->ct_magic == CT_MAGIC);
+
+	elog(WARNING, "cache reference leak: cache %s (%d), tuple %u/%u has count %d",
+		 ct->my_cache->cc_relname, ct->my_cache->id,
+		 ItemPointerGetBlockNumber(&(tuple->t_self)),
+		 ItemPointerGetOffsetNumber(&(tuple->t_self)),
+		 ct->refcount);
+}
+
+void
+PrintCatCacheListLeakWarning(CatCList *list)
+{
+	elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
+		 list->my_cache->cc_relname, list->my_cache->id,
+		 list, list->refcount);
+}
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index f3063ed9d93..d533a7697f6 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.10 2005/03/04 20:21:06 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.11 2005/03/25 18:30:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -87,6 +87,7 @@ static void ResourceOwnerReleaseInternal(ResourceOwner owner,
 							 ResourceReleasePhase phase,
 							 bool isCommit,
 							 bool isTopLevel);
+static void PrintRelCacheLeakWarning(Relation rel);
 
 
 /*****************************************************************************
@@ -231,7 +232,11 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
 			 * iterate till there are none.
 			 */
 			while (owner->nrelrefs > 0)
+			{
+				if (isCommit)
+					PrintRelCacheLeakWarning(owner->relrefs[owner->nrelrefs - 1]);
 				RelationClose(owner->relrefs[owner->nrelrefs - 1]);
+			}
 		}
 	}
 	else if (phase == RESOURCE_RELEASE_LOCKS)
@@ -284,9 +289,17 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
 			 * to iterate till there are none.	Ditto for catcache lists.
 			 */
 			while (owner->ncatrefs > 0)
+			{
+				if (isCommit)
+					PrintCatCacheLeakWarning(owner->catrefs[owner->ncatrefs - 1]);
 				ReleaseCatCache(owner->catrefs[owner->ncatrefs - 1]);
+			}
 			while (owner->ncatlistrefs > 0)
+			{
+				if (isCommit)
+					PrintCatCacheListLeakWarning(owner->catlistrefs[owner->ncatlistrefs - 1]);
 				ReleaseCatCacheList(owner->catlistrefs[owner->ncatlistrefs - 1]);
+			}
 		}
 		/* Clean up index scans too */
 		ReleaseResources_gist();
@@ -746,3 +759,13 @@ ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
 	elog(ERROR, "relcache reference %s is not owned by resource owner %s",
 		 RelationGetRelationName(rel), owner->name);
 }
+
+/*
+ * Debugging subroutine
+ */
+static void
+PrintRelCacheLeakWarning(Relation rel)
+{
+	elog(WARNING, "relcache reference leak: relation \"%s\" not closed",
+		 RelationGetRelationName(rel));
+}
diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h
index f08212d3f38..a9e6f19b9c5 100644
--- a/src/include/utils/catcache.h
+++ b/src/include/utils/catcache.h
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/catcache.h,v 1.52 2004/12/31 22:03:45 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/catcache.h,v 1.53 2005/03/25 18:30:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -187,4 +187,7 @@ extern void PrepareToInvalidateCacheTuple(Relation relation,
 							  HeapTuple tuple,
 					   void (*function) (int, uint32, ItemPointer, Oid));
 
+extern void PrintCatCacheLeakWarning(HeapTuple tuple);
+extern void PrintCatCacheListLeakWarning(CatCList *list);
+
 #endif   /* CATCACHE_H */
-- 
GitLab