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

Commit 467963c

Browse files
committed
Prevent query-lifespan memory leakage of SP-GiST traversal values.
The original coding of the SP-GiST scan traversalValue feature (commit ccd6eb4) arranged for traversal values to be stored in the query's main executor context. That's fine if there's only one index scan per query, but if there are many, we have a memory leak as successive scans create new traversal values. Fix it by creating a separate memory context for traversal values, which we can reset during spgrescan(). Back-patch to 9.6 where this code was introduced. In principle, adding the traversalCxt field to SpGistScanOpaqueData creates an ABI break in the back branches. But I (tgl) have little sympathy for extensions including spgist_private.h, so I'm not very worried about that. Alternatively we could stick the new field at the end of the struct in back branches, but that has its own downsides. Anton Dignös, reviewed by Alexander Kuzmenkov Discussion: https://postgr.es/m/CALNdv1jb6y2Te-m8xHLxLX12RsBmZJ1f4hESX7J0HjgyOhA9eA@mail.gmail.com
1 parent 13c7c65 commit 467963c

File tree

2 files changed

+9
-1
lines changed

2 files changed

+9
-1
lines changed

src/backend/access/spgist/spgscan.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
194194
so->tempCxt = AllocSetContextCreate(CurrentMemoryContext,
195195
"SP-GiST search temporary context",
196196
ALLOCSET_DEFAULT_SIZES);
197+
so->traversalCxt = AllocSetContextCreate(CurrentMemoryContext,
198+
"SP-GiST traversal-value context",
199+
ALLOCSET_DEFAULT_SIZES);
197200

198201
/* Set up indexTupDesc and xs_hitupdesc in case it's an index-only scan */
199202
so->indexTupDesc = scan->xs_hitupdesc = RelationGetDescr(rel);
@@ -209,6 +212,9 @@ spgrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
209212
{
210213
SpGistScanOpaque so = (SpGistScanOpaque) scan->opaque;
211214

215+
/* clear traversal context before proceeding to the next scan */
216+
MemoryContextReset(so->traversalCxt);
217+
212218
/* copy scankeys into local storage */
213219
if (scankey && scan->numberOfKeys > 0)
214220
{
@@ -229,6 +235,7 @@ spgendscan(IndexScanDesc scan)
229235
SpGistScanOpaque so = (SpGistScanOpaque) scan->opaque;
230236

231237
MemoryContextDelete(so->tempCxt);
238+
MemoryContextDelete(so->traversalCxt);
232239
}
233240

234241
/*
@@ -463,7 +470,7 @@ spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex,
463470
in.scankeys = so->keyData;
464471
in.nkeys = so->numberOfKeys;
465472
in.reconstructedValue = stackEntry->reconstructedValue;
466-
in.traversalMemoryContext = oldCtx;
473+
in.traversalMemoryContext = so->traversalCxt;
467474
in.traversalValue = stackEntry->traversalValue;
468475
in.level = stackEntry->level;
469476
in.returnData = so->want_itup;

src/include/access/spgist_private.h

+1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ typedef struct SpGistScanOpaqueData
137137
{
138138
SpGistState state; /* see above */
139139
MemoryContext tempCxt; /* short-lived memory context */
140+
MemoryContext traversalCxt; /* memory context for traversalValues */
140141

141142
/* Control flags showing whether to search nulls and/or non-nulls */
142143
bool searchNulls; /* scan matches (all) null entries */

0 commit comments

Comments
 (0)