From: Michael Paquier Date: Tue, 21 Jul 2026 07:50:18 +0000 (+0900) Subject: Improve generate_partition_qual()'s cache handling on out-of-memory errors X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fc6425fbe7a1fc7458fc27060ec78c5d98757690;p=thirdparty%2Fpostgresql.git Improve generate_partition_qual()'s cache handling on out-of-memory errors An in-flight failure when trying to set rd_partcheckcxt or rd_partcheck, while for example doing an allocation in copyObject(), would leave a backend cache in a corrupted state. The operations are now ordered so as we avoid a leak in the cache memory context and a semi-filled cache state when an allocation failure happens. This is unlikely going to be hit in practice. Like the other improvements of this kind, no backpatch is done. Reported-by: Alexander Lakhin Author: Matthias van de Meent Discussion: https://postgr.es/m/95c64dc2-3abe-4f4e-b285-4c681f565d9f@gmail.com --- diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c index 3107075c9ad..a0982674884 100644 --- a/src/backend/utils/cache/partcache.c +++ b/src/backend/utils/cache/partcache.c @@ -411,14 +411,31 @@ generate_partition_qual(Relation rel) */ if (result != NIL) { - rel->rd_partcheckcxt = AllocSetContextCreate(CacheMemoryContext, - "partition constraint", - ALLOCSET_SMALL_SIZES); - MemoryContextCopyAndSetIdentifier(rel->rd_partcheckcxt, + /* + * Take care to order operations so that allocation errors don't leave + * the catcache in an invalid state; first allocate everything into a + * transactional context, then associate it with CacheContext and + * update the relation data. This also avoids leaking memory if we + * ever hit OOM here. + */ + List *partcheck; + MemoryContext partctx; + + partctx = AllocSetContextCreate(CurrentMemoryContext, + "partition constraint", + ALLOCSET_SMALL_SIZES); + MemoryContextCopyAndSetIdentifier(partctx, RelationGetRelationName(rel)); - oldcxt = MemoryContextSwitchTo(rel->rd_partcheckcxt); - rel->rd_partcheck = copyObject(result); + + oldcxt = MemoryContextSwitchTo(partctx); + partcheck = copyObject(result); MemoryContextSwitchTo(oldcxt); + + /* finally, link the allocations and memctx into the right places */ + MemoryContextSetParent(partctx, CacheMemoryContext); + + rel->rd_partcheckcxt = partctx; + rel->rd_partcheck = partcheck; } else rel->rd_partcheck = NIL;