Commit 854ae8c3 authored by Alvaro Herrera's avatar Alvaro Herrera

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.
parent 947d0c86
...@@ -1754,6 +1754,9 @@ autovac_balance_cost(void) ...@@ -1754,6 +1754,9 @@ autovac_balance_cost(void)
* get_database_list * get_database_list
* Return a list of all databases found in pg_database. * Return a list of all databases found in pg_database.
* *
* The list and associated data is allocated in the caller's memory context,
* which is in charge of ensuring that it's properly cleaned up afterwards.
*
* Note: this is the only function in which the autovacuum launcher uses a * Note: this is the only function in which the autovacuum launcher uses a
* transaction. Although we aren't attached to any particular database and * transaction. Although we aren't attached to any particular database and
* therefore can't access most catalogs, we do have enough infrastructure * therefore can't access most catalogs, we do have enough infrastructure
...@@ -1766,6 +1769,10 @@ get_database_list(void) ...@@ -1766,6 +1769,10 @@ get_database_list(void)
Relation rel; Relation rel;
HeapScanDesc scan; HeapScanDesc scan;
HeapTuple tup; HeapTuple tup;
MemoryContext resultcxt;
/* This is the context that we will allocate our output data in */
resultcxt = CurrentMemoryContext;
/* /*
* Start a transaction so we can access pg_database, and get a snapshot. * Start a transaction so we can access pg_database, and get a snapshot.
...@@ -1777,9 +1784,6 @@ get_database_list(void) ...@@ -1777,9 +1784,6 @@ get_database_list(void)
StartTransactionCommand(); StartTransactionCommand();
(void) GetTransactionSnapshot(); (void) GetTransactionSnapshot();
/* Allocate our results in AutovacMemCxt, not transaction context */
MemoryContextSwitchTo(AutovacMemCxt);
rel = heap_open(DatabaseRelationId, AccessShareLock); rel = heap_open(DatabaseRelationId, AccessShareLock);
scan = heap_beginscan(rel, SnapshotNow, 0, NULL); scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
...@@ -1787,6 +1791,15 @@ get_database_list(void) ...@@ -1787,6 +1791,15 @@ get_database_list(void)
{ {
Form_pg_database pgdatabase = (Form_pg_database) GETSTRUCT(tup); Form_pg_database pgdatabase = (Form_pg_database) GETSTRUCT(tup);
avw_dbase *avdb; avw_dbase *avdb;
MemoryContext oldcxt;
/*
* Allocate our results in the caller's context, not the transaction's.
* We do this inside the loop, and restore the original context at the
* end, so that leaky things like heap_getnext() are not called in a
* potentially long-lived context.
*/
oldcxt = MemoryContextSwitchTo(resultcxt);
avdb = (avw_dbase *) palloc(sizeof(avw_dbase)); avdb = (avw_dbase *) palloc(sizeof(avw_dbase));
...@@ -1797,6 +1810,7 @@ get_database_list(void) ...@@ -1797,6 +1810,7 @@ get_database_list(void)
avdb->adw_entry = NULL; avdb->adw_entry = NULL;
dblist = lappend(dblist, avdb); dblist = lappend(dblist, avdb);
MemoryContextSwitchTo(oldcxt);
} }
heap_endscan(scan); heap_endscan(scan);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment