Commit 08890b40 authored by Tom Lane's avatar Tom Lane

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.
parent 6b7ef076
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -556,8 +556,7 @@ AtEOXact_CatCache(bool isCommit)
if (cl->refcount != 0) if (cl->refcount != 0)
{ {
if (isCommit) if (isCommit)
elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d", PrintCatCacheListLeakWarning(cl);
ccp->cc_relname, ccp->id, cl, cl->refcount);
cl->refcount = 0; cl->refcount = 0;
} }
...@@ -579,10 +578,7 @@ AtEOXact_CatCache(bool isCommit) ...@@ -579,10 +578,7 @@ AtEOXact_CatCache(bool isCommit)
if (ct->refcount != 0) if (ct->refcount != 0)
{ {
if (isCommit) if (isCommit)
elog(WARNING, "cache reference leak: cache %s (%d), tuple %u has count %d", PrintCatCacheLeakWarning(&ct->tuple);
ct->my_cache->cc_relname, ct->my_cache->id,
HeapTupleGetOid(&ct->tuple),
ct->refcount);
ct->refcount = 0; ct->refcount = 0;
} }
...@@ -1807,3 +1803,32 @@ PrepareToInvalidateCacheTuple(Relation relation, ...@@ -1807,3 +1803,32 @@ PrepareToInvalidateCacheTuple(Relation relation,
ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId); 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);
}
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -87,6 +87,7 @@ static void ResourceOwnerReleaseInternal(ResourceOwner owner,
ResourceReleasePhase phase, ResourceReleasePhase phase,
bool isCommit, bool isCommit,
bool isTopLevel); bool isTopLevel);
static void PrintRelCacheLeakWarning(Relation rel);
/***************************************************************************** /*****************************************************************************
...@@ -231,7 +232,11 @@ ResourceOwnerReleaseInternal(ResourceOwner owner, ...@@ -231,7 +232,11 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
* iterate till there are none. * iterate till there are none.
*/ */
while (owner->nrelrefs > 0) while (owner->nrelrefs > 0)
{
if (isCommit)
PrintRelCacheLeakWarning(owner->relrefs[owner->nrelrefs - 1]);
RelationClose(owner->relrefs[owner->nrelrefs - 1]); RelationClose(owner->relrefs[owner->nrelrefs - 1]);
}
} }
} }
else if (phase == RESOURCE_RELEASE_LOCKS) else if (phase == RESOURCE_RELEASE_LOCKS)
...@@ -284,9 +289,17 @@ ResourceOwnerReleaseInternal(ResourceOwner owner, ...@@ -284,9 +289,17 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
* to iterate till there are none. Ditto for catcache lists. * to iterate till there are none. Ditto for catcache lists.
*/ */
while (owner->ncatrefs > 0) while (owner->ncatrefs > 0)
{
if (isCommit)
PrintCatCacheLeakWarning(owner->catrefs[owner->ncatrefs - 1]);
ReleaseCatCache(owner->catrefs[owner->ncatrefs - 1]); ReleaseCatCache(owner->catrefs[owner->ncatrefs - 1]);
}
while (owner->ncatlistrefs > 0) while (owner->ncatlistrefs > 0)
{
if (isCommit)
PrintCatCacheListLeakWarning(owner->catlistrefs[owner->ncatlistrefs - 1]);
ReleaseCatCacheList(owner->catlistrefs[owner->ncatlistrefs - 1]); ReleaseCatCacheList(owner->catlistrefs[owner->ncatlistrefs - 1]);
}
} }
/* Clean up index scans too */ /* Clean up index scans too */
ReleaseResources_gist(); ReleaseResources_gist();
...@@ -746,3 +759,13 @@ ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel) ...@@ -746,3 +759,13 @@ ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
elog(ERROR, "relcache reference %s is not owned by resource owner %s", elog(ERROR, "relcache reference %s is not owned by resource owner %s",
RelationGetRelationName(rel), owner->name); RelationGetRelationName(rel), owner->name);
} }
/*
* Debugging subroutine
*/
static void
PrintRelCacheLeakWarning(Relation rel)
{
elog(WARNING, "relcache reference leak: relation \"%s\" not closed",
RelationGetRelationName(rel));
}
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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, ...@@ -187,4 +187,7 @@ extern void PrepareToInvalidateCacheTuple(Relation relation,
HeapTuple tuple, HeapTuple tuple,
void (*function) (int, uint32, ItemPointer, Oid)); void (*function) (int, uint32, ItemPointer, Oid));
extern void PrintCatCacheLeakWarning(HeapTuple tuple);
extern void PrintCatCacheListLeakWarning(CatCList *list);
#endif /* CATCACHE_H */ #endif /* CATCACHE_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment