Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ab8c84d

Browse files
committed
Prevent memory leaks in RelationGetIndexList, RelationGetIndexAttrBitmap.
When replacing rd_indexlist, rd_indexattr, etc, we neglected to pfree any old value of these fields. Under ordinary circumstances, the old value would always be NULL, so this seemed reasonable enough. However, in cases where we're rebuilding a system catalog's relcache entry and another cache flush occurs on that same catalog meanwhile, it's possible for the field to not be NULL when we return to the outer level, because we already refilled it while recovering from the inner flush. This leads to a fairly small session-lifespan leak in CacheMemoryContext. In real-world usage the leak would be too small to notice; but in testing with CLOBBER_CACHE_RECURSIVELY the leakage can add up to the point of causing OOM failures, as reported by Tomas Vondra. The issue has been there a long time, but it only seems worth fixing in HEAD, like the previous fix in this area (commit 078b2ed).
1 parent 52bffe3 commit ab8c84d

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

src/backend/utils/cache/relcache.c

+13
Original file line numberDiff line numberDiff line change
@@ -3646,6 +3646,7 @@ RelationGetIndexList(Relation relation)
36463646
ScanKeyData skey;
36473647
HeapTuple htup;
36483648
List *result;
3649+
List *oldlist;
36493650
char replident = relation->rd_rel->relreplident;
36503651
Oid oidIndex = InvalidOid;
36513652
Oid pkeyIndex = InvalidOid;
@@ -3737,6 +3738,7 @@ RelationGetIndexList(Relation relation)
37373738

37383739
/* Now save a copy of the completed list in the relcache entry. */
37393740
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
3741+
oldlist = relation->rd_indexlist;
37403742
relation->rd_indexlist = list_copy(result);
37413743
relation->rd_oidindex = oidIndex;
37423744
if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
@@ -3748,6 +3750,9 @@ RelationGetIndexList(Relation relation)
37483750
relation->rd_indexvalid = 1;
37493751
MemoryContextSwitchTo(oldcxt);
37503752

3753+
/* Don't leak the old list, if there is one */
3754+
list_free(oldlist);
3755+
37513756
return result;
37523757
}
37533758

@@ -4141,6 +4146,14 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
41414146

41424147
list_free(indexoidlist);
41434148

4149+
/* Don't leak the old values of these bitmaps, if any */
4150+
bms_free(relation->rd_indexattr);
4151+
relation->rd_indexattr = NULL;
4152+
bms_free(relation->rd_keyattr);
4153+
relation->rd_keyattr = NULL;
4154+
bms_free(relation->rd_idattr);
4155+
relation->rd_idattr = NULL;
4156+
41444157
/*
41454158
* Now save copies of the bitmaps in the relcache entry. We intentionally
41464159
* set rd_indexattr last, because that's the one that signals validity of

0 commit comments

Comments
 (0)