diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2010-11-08 18:35:42 -0300 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2010-11-08 18:35:42 -0300 |
commit | 854ae8c3a6bab2053f8bdbc453787be878ce8c81 (patch) | |
tree | b2514853fdfe200912a73366aa58c70aca55bf79 /src | |
parent | 947d0c862c895618a874344322e7b07c9df05cb2 (diff) | |
download | postgresql-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/postmaster/autovacuum.c | 20 |
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); |