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

Commit 854ae8c

Browse files
committed
Fix permanent memory leak in autovacuum launcher
get_database_list was uselessly allocating its output data, along some created along the way, in a permanent memory context. This didn't matter when autovacuum was a single, short-lived process, but now that the launcher is permanent, it shows up as a permanent leak. To fix, make get_database list allocate its output data in the caller's context, which is in charge of freeing it when appropriate; and the memory leaked by heap_beginscan et al is allocated in a throwaway transaction context.
1 parent 947d0c8 commit 854ae8c

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

src/backend/postmaster/autovacuum.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,6 +1754,9 @@ autovac_balance_cost(void)
17541754
* get_database_list
17551755
* Return a list of all databases found in pg_database.
17561756
*
1757+
* The list and associated data is allocated in the caller's memory context,
1758+
* which is in charge of ensuring that it's properly cleaned up afterwards.
1759+
*
17571760
* Note: this is the only function in which the autovacuum launcher uses a
17581761
* transaction. Although we aren't attached to any particular database and
17591762
* therefore can't access most catalogs, we do have enough infrastructure
@@ -1766,6 +1769,10 @@ get_database_list(void)
17661769
Relation rel;
17671770
HeapScanDesc scan;
17681771
HeapTuple tup;
1772+
MemoryContext resultcxt;
1773+
1774+
/* This is the context that we will allocate our output data in */
1775+
resultcxt = CurrentMemoryContext;
17691776

17701777
/*
17711778
* Start a transaction so we can access pg_database, and get a snapshot.
@@ -1777,16 +1784,22 @@ get_database_list(void)
17771784
StartTransactionCommand();
17781785
(void) GetTransactionSnapshot();
17791786

1780-
/* Allocate our results in AutovacMemCxt, not transaction context */
1781-
MemoryContextSwitchTo(AutovacMemCxt);
1782-
17831787
rel = heap_open(DatabaseRelationId, AccessShareLock);
17841788
scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
17851789

17861790
while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
17871791
{
17881792
Form_pg_database pgdatabase = (Form_pg_database) GETSTRUCT(tup);
17891793
avw_dbase *avdb;
1794+
MemoryContext oldcxt;
1795+
1796+
/*
1797+
* Allocate our results in the caller's context, not the transaction's.
1798+
* We do this inside the loop, and restore the original context at the
1799+
* end, so that leaky things like heap_getnext() are not called in a
1800+
* potentially long-lived context.
1801+
*/
1802+
oldcxt = MemoryContextSwitchTo(resultcxt);
17901803

17911804
avdb = (avw_dbase *) palloc(sizeof(avw_dbase));
17921805

@@ -1797,6 +1810,7 @@ get_database_list(void)
17971810
avdb->adw_entry = NULL;
17981811

17991812
dblist = lappend(dblist, avdb);
1813+
MemoryContextSwitchTo(oldcxt);
18001814
}
18011815

18021816
heap_endscan(scan);

0 commit comments

Comments
 (0)