]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Limit memory usage of pg_walinspect functions.
authorJeff Davis <jdavis@postgresql.org>
Mon, 20 Feb 2023 19:29:31 +0000 (11:29 -0800)
committerJeff Davis <jdavis@postgresql.org>
Mon, 20 Feb 2023 19:29:31 +0000 (11:29 -0800)
GetWALRecordsInfo() and pg_get_wal_fpi_info() can leak memory across
WAL record iterations. Fix this by using a temporary memory context
that's reset for each WAL record iteraion.

Also use a temporary context for loops in GetXLogSummaryStats(). The
number of iterations is a small constant, so the previous behavior was
not a leak, but fix for clarity (but no need to backport).

Backport GetWALRecordsInfo() change to version
15. pg_get_wal_fpi_info() didn't exist in version 15.

Reported-by: Peter Geoghegan
Author: Bharath Rupireddy
Discussion: https://www.postgresql.org/message-id/CAH2-WznLEJjn7ghmKOABOEZYuJvkTk%3DGKU3m0%2B-XBAH%2BerPiJQ%40mail.gmail.com
Backpatch-through: 15

contrib/pg_walinspect/pg_walinspect.c

index 6b6c7d46e27daf4a73edb4a8da0d786d36fa924c..826c9345aeae629a09c6ec1e1a22e0b6378c2ad4 100644 (file)
@@ -332,6 +332,8 @@ GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
        ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
        Datum           values[PG_GET_WAL_RECORDS_INFO_COLS];
        bool            nulls[PG_GET_WAL_RECORDS_INFO_COLS];
+       MemoryContext old_cxt;
+       MemoryContext tmp_cxt;
 
        InitMaterializedSRF(fcinfo, 0);
 
@@ -340,18 +342,30 @@ GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
        MemSet(values, 0, sizeof(values));
        MemSet(nulls, 0, sizeof(nulls));
 
+       tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
+                                                                       "GetWALRecordsInfo temporary cxt",
+                                                                       ALLOCSET_DEFAULT_SIZES);
+
        while (ReadNextXLogRecord(xlogreader) &&
                   xlogreader->EndRecPtr <= end_lsn)
        {
+               /* Use the tmp context so we can clean up after each tuple is done */
+               old_cxt = MemoryContextSwitchTo(tmp_cxt);
+
                GetWALRecordInfo(xlogreader, values, nulls,
                                                 PG_GET_WAL_RECORDS_INFO_COLS);
 
                tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
                                                         values, nulls);
 
+               /* clean up and switch back */
+               MemoryContextSwitchTo(old_cxt);
+               MemoryContextReset(tmp_cxt);
+
                CHECK_FOR_INTERRUPTS();
        }
 
+       MemoryContextDelete(tmp_cxt);
        pfree(xlogreader->private_data);
        XLogReaderFree(xlogreader);