Thread

  1. Re: lsyscache: free IndexAmRoutine objects returned by GetIndexAmRoutineByAmId()

    Álvaro Herrera <alvherre@kurilemu.de> — 2025-12-30T14:15:26Z

    On 2025-Dec-29, Tom Lane wrote:
    
    > The main objection that could be raised to this is that the old coding
    > ensures that any memory leaked during GetIndexAmRoutine() will be
    > leaked in the expected-to-be-short-lived caller's context, but now
    > it'd be leaked in the cache's rd_indexcxt.
    
    One thing we can perhaps do is (in assert-enabled builds) to detect
    whether memory usage for that context has increased during
    InitIndexAmRoutine and raise a warning if so.  Then extension authors
    would realize this and have a chance to fix it promptly.
    
    I tried this out and it doesn't work as well as I thought, due to how
    AllocSet works: we don't get a difference in the amount of allocated
    memory (thus no WARNING) unless we add some padding bytes to
    IndexAmRoutine, as shown below (of course, just POC-quality -- didn't
    kry to compile without assertions).  Given this, I'm not terribly
    optimistic about this idea.  I tested this by adding
    palloc(sizeof(IndexAmRoutine)) in brinhandler() and verifying that a few
    regression tests fail with the added warning message.
    
    
    diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
    index 88259f7c228..75f2a2f5e37 100644
    --- a/src/backend/utils/cache/relcache.c
    +++ b/src/backend/utils/cache/relcache.c
    @@ -1421,6 +1421,7 @@ static void
     InitIndexAmRoutine(Relation relation)
     {
     	MemoryContext oldctx;
    +	Size	allocated	PG_USED_FOR_ASSERTS_ONLY;
     
     	/*
     	 * We formerly specified that the amhandler should return a palloc'd
    @@ -1429,7 +1430,19 @@ InitIndexAmRoutine(Relation relation)
     	 * the amhandler in the relation's rd_indexcxt.
     	 */
     	oldctx = MemoryContextSwitchTo(relation->rd_indexcxt);
    +
    +#ifdef USE_ASSERT_CHECKING
    +	allocated = MemoryContextMemAllocated(CurrentMemoryContext, false);
    +#endif
    +
     	relation->rd_indam = GetIndexAmRoutine(relation->rd_amhandler);
    +
    +#ifdef USE_ASSERT_CHECKING
    +	if (MemoryContextMemAllocated(CurrentMemoryContext, false) - allocated != 0)
    +		elog(WARNING, "memory allocated while initializing access method %u (was %zu, now %zu)",
    +			 relation->rd_amhandler, allocated, MemoryContextMemAllocated(CurrentMemoryContext, false));
    +#endif
    +
     	MemoryContextSwitchTo(oldctx);
     }
     
    diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h
    index 278da36bc08..78fcbcffc14 100644
    --- a/src/include/access/amapi.h
    +++ b/src/include/access/amapi.h
    @@ -322,6 +322,11 @@ typedef struct IndexAmRoutine
     	/* interface functions to support planning */
     	amtranslate_strategy_function amtranslatestrategy;	/* can be NULL */
     	amtranslate_cmptype_function amtranslatecmptype;	/* can be NULL */
    +
    +#ifdef USE_ASSERT_CHECKING
    +	char		pad[512];
    +#endif
    +
     } IndexAmRoutine;
    
    -- 
    Álvaro Herrera         PostgreSQL Developer  —  https://www.EnterpriseDB.com/