aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2010-11-08 18:35:42 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2010-11-08 18:35:42 -0300
commit854ae8c3a6bab2053f8bdbc453787be878ce8c81 (patch)
treeb2514853fdfe200912a73366aa58c70aca55bf79
parent947d0c862c895618a874344322e7b07c9df05cb2 (diff)
downloadpostgresql-854ae8c3a6bab2053f8bdbc453787be878ce8c81.tar.gz
postgresql-854ae8c3a6bab2053f8bdbc453787be878ce8c81.zip
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.
-rw-r--r--src/backend/postmaster/autovacuum.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index e7176448a0e..a617b882a34 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -1754,6 +1754,9 @@ autovac_balance_cost(void)
* get_database_list
* 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
* transaction. Although we aren't attached to any particular database and
* therefore can't access most catalogs, we do have enough infrastructure
@@ -1766,6 +1769,10 @@ get_database_list(void)
Relation rel;
HeapScanDesc scan;
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.
@@ -1777,9 +1784,6 @@ get_database_list(void)
StartTransactionCommand();
(void) GetTransactionSnapshot();
- /* Allocate our results in AutovacMemCxt, not transaction context */
- MemoryContextSwitchTo(AutovacMemCxt);
-
rel = heap_open(DatabaseRelationId, AccessShareLock);
scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
@@ -1787,6 +1791,15 @@ get_database_list(void)
{
Form_pg_database pgdatabase = (Form_pg_database) GETSTRUCT(tup);
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));
@@ -1797,6 +1810,7 @@ get_database_list(void)
avdb->adw_entry = NULL;
dblist = lappend(dblist, avdb);
+ MemoryContextSwitchTo(oldcxt);
}
heap_endscan(scan);