aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/spgist
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-10-31 17:04:42 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2018-10-31 17:05:03 -0400
commit696b0c5fd0a8765fe6dfd075a30be06b448fd615 (patch)
tree2c7d3b075ed6ef1a3c3bb6e5520587c4ba6ac561 /src/backend/access/spgist
parentc4ab62f9acc0389697042cb642aa74beabdc8cc7 (diff)
downloadpostgresql-696b0c5fd0a8765fe6dfd075a30be06b448fd615.tar.gz
postgresql-696b0c5fd0a8765fe6dfd075a30be06b448fd615.zip
Fix memory leak in repeated SPGIST index scans.
spgendscan neglected to pfree all the memory allocated by spgbeginscan. It's possible to get away with that in most normal queries, since the memory is allocated in the executor's per-query context which is about to get deleted anyway; but it causes severe memory leakage during creation or filling of large exclusion-constraint indexes. Also, document that amendscan is supposed to free what ambeginscan allocates. The docs' lack of clarity on that point probably caused this bug to begin with. (There is discussion of changing that API spec going forward, but I don't think it'd be appropriate for the back branches.) Per report from Bruno Wolff. It's been like this since the beginning, so back-patch to all active branches. In HEAD, also fix an independent leak caused by commit 2a6368343 (allocating memory during spgrescan instead of spgbeginscan, which might be all right if it got cleaned up, but it didn't). And do a bit of code beautification on that commit, too. Discussion: https://postgr.es/m/20181024012314.GA27428@wolff.to
Diffstat (limited to 'src/backend/access/spgist')
-rw-r--r--src/backend/access/spgist/spgscan.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c
index a63fde2c8af..c883ae95e48 100644
--- a/src/backend/access/spgist/spgscan.c
+++ b/src/backend/access/spgist/spgscan.c
@@ -294,10 +294,18 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
/* Set up indexTupDesc and xs_hitupdesc in case it's an index-only scan */
so->indexTupDesc = scan->xs_hitupdesc = RelationGetDescr(rel);
+ /* Allocate various arrays needed for order-by scans */
if (scan->numberOfOrderBys > 0)
{
- so->zeroDistances = palloc(sizeof(double) * scan->numberOfOrderBys);
- so->infDistances = palloc(sizeof(double) * scan->numberOfOrderBys);
+ /* This will be filled in spgrescan, but allocate the space here */
+ so->orderByTypes = (Oid *)
+ palloc(sizeof(Oid) * scan->numberOfOrderBys);
+
+ /* These arrays have constant contents, so we can fill them now */
+ so->zeroDistances = (double *)
+ palloc(sizeof(double) * scan->numberOfOrderBys);
+ so->infDistances = (double *)
+ palloc(sizeof(double) * scan->numberOfOrderBys);
for (i = 0; i < scan->numberOfOrderBys; i++)
{
@@ -305,9 +313,12 @@ spgbeginscan(Relation rel, int keysz, int orderbysz)
so->infDistances[i] = get_float8_infinity();
}
- scan->xs_orderbyvals = palloc0(sizeof(Datum) * scan->numberOfOrderBys);
- scan->xs_orderbynulls = palloc(sizeof(bool) * scan->numberOfOrderBys);
- memset(scan->xs_orderbynulls, true, sizeof(bool) * scan->numberOfOrderBys);
+ scan->xs_orderbyvals = (Datum *)
+ palloc0(sizeof(Datum) * scan->numberOfOrderBys);
+ scan->xs_orderbynulls = (bool *)
+ palloc(sizeof(bool) * scan->numberOfOrderBys);
+ memset(scan->xs_orderbynulls, true,
+ sizeof(bool) * scan->numberOfOrderBys);
}
fmgr_info_copy(&so->innerConsistentFn,
@@ -336,6 +347,7 @@ spgrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
memmove(scan->keyData, scankey,
scan->numberOfKeys * sizeof(ScanKeyData));
+ /* initialize order-by data if needed */
if (orderbys && scan->numberOfOrderBys > 0)
{
int i;
@@ -343,8 +355,6 @@ spgrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
memmove(scan->orderByData, orderbys,
scan->numberOfOrderBys * sizeof(ScanKeyData));
- so->orderByTypes = (Oid *) palloc(sizeof(Oid) * scan->numberOfOrderBys);
-
for (i = 0; i < scan->numberOfOrderBys; i++)
{
ScanKey skey = &scan->orderByData[i];
@@ -380,11 +390,22 @@ spgendscan(IndexScanDesc scan)
MemoryContextDelete(so->tempCxt);
MemoryContextDelete(so->traversalCxt);
+ if (so->keyData)
+ pfree(so->keyData);
+
+ if (so->state.deadTupleStorage)
+ pfree(so->state.deadTupleStorage);
+
if (scan->numberOfOrderBys > 0)
{
+ pfree(so->orderByTypes);
pfree(so->zeroDistances);
pfree(so->infDistances);
+ pfree(scan->xs_orderbyvals);
+ pfree(scan->xs_orderbynulls);
}
+
+ pfree(so);
}
/*