]> granicus.if.org Git - postgresql/commitdiff
Remove AtEOXact_CatCache().
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 13 Aug 2017 20:15:14 +0000 (16:15 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 13 Aug 2017 20:15:14 +0000 (16:15 -0400)
The sole useful effect of this function, to check that no catcache
entries have positive refcounts at transaction end, has really been
obsolete since we introduced ResourceOwners in PG 8.1.  We reduced the
checks to assertions years ago, so that the function was a complete
no-op in production builds.  There have been previous discussions about
removing it entirely, but consensus up to now was that it had some small
value as a cross-check for bugs in the ResourceOwner logic.

However, it now emerges that it's possible to trigger these assertions
if you hit an assert-enabled backend with SIGTERM during a call to
SearchCatCacheList, because that function temporarily increases the
refcounts of entries it's intending to add to a catcache list construct.
In a normal ERROR scenario, the extra refcounts are cleaned up by
SearchCatCacheList's PG_CATCH block; but in a FATAL exit we do a
transaction abort and exit without ever executing PG_CATCH handlers.

There's a case to be made that this is a generic hazard and we should
consider restructuring elog(FATAL) handling so that pending PG_CATCH
handlers do get run.  That's pretty scary though: it could easily create
more problems than it solves.  Preliminary stress testing by Andreas
Seltenreich suggests that there are not many live problems of this ilk,
so we rejected that idea.

There are more-localized ways to fix the problem; the most principled
one would be to use PG_ENSURE_ERROR_CLEANUP instead of plain PG_TRY.
But adding cycles to SearchCatCacheList isn't very appealing.  We could
also weaken the assertions in AtEOXact_CatCache in some more or less
ad-hoc way, but that just makes its raison d'etre even less compelling.
In the end, the most reasonable solution seems to be to just remove
AtEOXact_CatCache altogether, on the grounds that it's not worth trying
to fix it.  It hasn't found any bugs for us in many years.

Per report from Jeevan Chalke.  Back-patch to all supported branches.

Discussion: https://postgr.es/m/CAM2+6=VEE30YtRQCZX7_sCFsEpoUkFBV1gZazL70fqLn8rcvBA@mail.gmail.com

src/backend/access/transam/xact.c
src/backend/utils/cache/catcache.c
src/include/utils/catcache.h

index 50c3c3b5e5e3763d795294cf545c1f1bdaa6f0ed..a8fbd043ae530537db87060c831f1b0136a4cc3a 100644 (file)
@@ -2124,9 +2124,6 @@ CommitTransaction(void)
         */
        smgrDoPendingDeletes(true);
 
-       /* Check we've released all catcache entries */
-       AtEOXact_CatCache(true);
-
        AtCommit_Notify();
        AtEOXact_GUC(true, 1);
        AtEOXact_SPI(true);
@@ -2405,9 +2402,6 @@ PrepareTransaction(void)
         */
        PostPrepare_Twophase();
 
-       /* Check we've released all catcache entries */
-       AtEOXact_CatCache(true);
-
        /* PREPARE acts the same as COMMIT as far as GUC is concerned */
        AtEOXact_GUC(true, 1);
        AtEOXact_SPI(true);
@@ -2610,7 +2604,6 @@ AbortTransaction(void)
                                                         RESOURCE_RELEASE_AFTER_LOCKS,
                                                         false, true);
                smgrDoPendingDeletes(false);
-               AtEOXact_CatCache(false);
 
                AtEOXact_GUC(false, 1);
                AtEOXact_SPI(false);
index e7e8e3b54c5531fca621f7c57446f2cd3c65fa3c..f894053d80676d9eabb87020fe63aefde63b502e 100644 (file)
@@ -521,57 +521,6 @@ CreateCacheMemoryContext(void)
 }
 
 
-/*
- *             AtEOXact_CatCache
- *
- * Clean up catcaches at end of main transaction (either commit or abort)
- *
- * As of PostgreSQL 8.1, catcache pins should get released by the
- * ResourceOwner mechanism.  This routine is just a debugging
- * cross-check that no pins remain.
- */
-void
-AtEOXact_CatCache(bool isCommit)
-{
-#ifdef USE_ASSERT_CHECKING
-       slist_iter      cache_iter;
-
-       slist_foreach(cache_iter, &CacheHdr->ch_caches)
-       {
-               CatCache   *ccp = slist_container(CatCache, cc_next, cache_iter.cur);
-               dlist_iter      iter;
-               int                     i;
-
-               /* Check CatCLists */
-               dlist_foreach(iter, &ccp->cc_lists)
-               {
-                       CatCList   *cl;
-
-                       cl = dlist_container(CatCList, cache_elem, iter.cur);
-                       Assert(cl->cl_magic == CL_MAGIC);
-                       Assert(cl->refcount == 0);
-                       Assert(!cl->dead);
-               }
-
-               /* Check individual tuples */
-               for (i = 0; i < ccp->cc_nbuckets; i++)
-               {
-                       dlist_head *bucket = &ccp->cc_bucket[i];
-
-                       dlist_foreach(iter, bucket)
-                       {
-                               CatCTup    *ct;
-
-                               ct = dlist_container(CatCTup, cache_elem, iter.cur);
-                               Assert(ct->ct_magic == CT_MAGIC);
-                               Assert(ct->refcount == 0);
-                               Assert(!ct->dead);
-                       }
-               }
-       }
-#endif
-}
-
 /*
  *             ResetCatalogCache
  *
index f8ebc903d321b6d1c438c21ea0fe5c2658e02514..200a3022e7bf6d91944156895ce75b2c45ffe2e6 100644 (file)
@@ -167,7 +167,6 @@ typedef struct catcacheheader
 extern PGDLLIMPORT MemoryContext CacheMemoryContext;
 
 extern void CreateCacheMemoryContext(void);
-extern void AtEOXact_CatCache(bool isCommit);
 
 extern CatCache *InitCatCache(int id, Oid reloid, Oid indexoid,
                         int nkeys, const int *key,