mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Fix assorted pretty-trivial memory leaks in the backend.
In the current system architecture, none of these are worth obsessing over; most are once-per-process leaks. However, Valgrind complains about all of them, and if we get to using threads rather than processes for backend sessions, it will become more interesting to avoid per-session leaks. * Fix leaks in StartupXLOG() and ShutdownWalRecovery(). * Fix leakage of pq_mq_handle in a parallel worker. While at it, move mq_putmessage's "Assert(pq_mq_handle != NULL)" to someplace where it's not trivially useless. * Fix leak in logicalrep_worker_detach(). * Don't leak the startup-packet buffer in ProcessStartupPacket(). * Fix leak in evtcache.c's DecodeTextArrayToBitmapset(). If the presented array is toasted, this neglected to free the detoasted copy, which was then leaked into EventTriggerCacheContext. * I'm distressed by the amount of code that BuildEventTriggerCache is willing to run while switched into a long-lived cache context. Although the detoasted array is the only leak that Valgrind reports, let's tighten things up while we're here. (DecodeTextArrayToBitmapset is still run in the cache context, so doing this doesn't remove the need for the detoast fix. But it reduces the surface area for other leaks.) * load_domaintype_info() intentionally leaked some intermediate cruft into the long-lived DomainConstraintCache's memory context, reasoning that the amount of leakage will typically not be much so it's not worth doing a copyObject() of the final tree to avoid that. But Valgrind knows nothing of engineering tradeoffs and complains anyway. On the whole, the copyObject doesn't cost that much and this is surely not a performance-critical code path, so let's do it the clean way. * MarkGUCPrefixReserved didn't bother to clean up removed placeholder GUCs at all, which shows up as a leak in one regression test. It seems appropriate for it to do as much cleanup as define_custom_variable does when replacing placeholders, so factor that code out into a helper function. define_custom_variable's logic was one brick shy of a load too: it forgot to free the separate allocation for the placeholder's name. Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Andres Freund <andres@anarazel.de> Reviewed-by: Richard Guo <guofenglinux@gmail.com> Discussion: https://postgr.es/m/285483.1746756246@sss.pgh.pa.us
This commit is contained in:
16
src/backend/utils/cache/evtcache.c
vendored
16
src/backend/utils/cache/evtcache.c
vendored
@@ -78,7 +78,6 @@ BuildEventTriggerCache(void)
|
||||
{
|
||||
HASHCTL ctl;
|
||||
HTAB *cache;
|
||||
MemoryContext oldcontext;
|
||||
Relation rel;
|
||||
Relation irel;
|
||||
SysScanDesc scan;
|
||||
@@ -110,9 +109,6 @@ BuildEventTriggerCache(void)
|
||||
(Datum) 0);
|
||||
}
|
||||
|
||||
/* Switch to correct memory context. */
|
||||
oldcontext = MemoryContextSwitchTo(EventTriggerCacheContext);
|
||||
|
||||
/* Prevent the memory context from being nuked while we're rebuilding. */
|
||||
EventTriggerCacheState = ETCS_REBUILD_STARTED;
|
||||
|
||||
@@ -145,6 +141,7 @@ BuildEventTriggerCache(void)
|
||||
bool evttags_isnull;
|
||||
EventTriggerCacheEntry *entry;
|
||||
bool found;
|
||||
MemoryContext oldcontext;
|
||||
|
||||
/* Get next tuple. */
|
||||
tup = systable_getnext_ordered(scan, ForwardScanDirection);
|
||||
@@ -171,6 +168,9 @@ BuildEventTriggerCache(void)
|
||||
else
|
||||
continue;
|
||||
|
||||
/* Switch to correct memory context. */
|
||||
oldcontext = MemoryContextSwitchTo(EventTriggerCacheContext);
|
||||
|
||||
/* Allocate new cache item. */
|
||||
item = palloc0(sizeof(EventTriggerCacheItem));
|
||||
item->fnoid = form->evtfoid;
|
||||
@@ -188,6 +188,9 @@ BuildEventTriggerCache(void)
|
||||
entry->triggerlist = lappend(entry->triggerlist, item);
|
||||
else
|
||||
entry->triggerlist = list_make1(item);
|
||||
|
||||
/* Restore previous memory context. */
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
}
|
||||
|
||||
/* Done with pg_event_trigger scan. */
|
||||
@@ -195,9 +198,6 @@ BuildEventTriggerCache(void)
|
||||
index_close(irel, AccessShareLock);
|
||||
relation_close(rel, AccessShareLock);
|
||||
|
||||
/* Restore previous memory context. */
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
||||
/* Install new cache. */
|
||||
EventTriggerCache = cache;
|
||||
|
||||
@@ -240,6 +240,8 @@ DecodeTextArrayToBitmapset(Datum array)
|
||||
}
|
||||
|
||||
pfree(elems);
|
||||
if ((Pointer) arr != DatumGetPointer(array))
|
||||
pfree(arr);
|
||||
|
||||
return bms;
|
||||
}
|
||||
|
||||
13
src/backend/utils/cache/typcache.c
vendored
13
src/backend/utils/cache/typcache.c
vendored
@@ -1171,9 +1171,6 @@ load_domaintype_info(TypeCacheEntry *typentry)
|
||||
elog(ERROR, "domain \"%s\" constraint \"%s\" has NULL conbin",
|
||||
NameStr(typTup->typname), NameStr(c->conname));
|
||||
|
||||
/* Convert conbin to C string in caller context */
|
||||
constring = TextDatumGetCString(val);
|
||||
|
||||
/* Create the DomainConstraintCache object and context if needed */
|
||||
if (dcc == NULL)
|
||||
{
|
||||
@@ -1189,9 +1186,8 @@ load_domaintype_info(TypeCacheEntry *typentry)
|
||||
dcc->dccRefCount = 0;
|
||||
}
|
||||
|
||||
/* Create node trees in DomainConstraintCache's context */
|
||||
oldcxt = MemoryContextSwitchTo(dcc->dccContext);
|
||||
|
||||
/* Convert conbin to a node tree, still in caller's context */
|
||||
constring = TextDatumGetCString(val);
|
||||
check_expr = (Expr *) stringToNode(constring);
|
||||
|
||||
/*
|
||||
@@ -1206,10 +1202,13 @@ load_domaintype_info(TypeCacheEntry *typentry)
|
||||
*/
|
||||
check_expr = expression_planner(check_expr);
|
||||
|
||||
/* Create only the minimally needed stuff in dccContext */
|
||||
oldcxt = MemoryContextSwitchTo(dcc->dccContext);
|
||||
|
||||
r = makeNode(DomainConstraintState);
|
||||
r->constrainttype = DOM_CONSTRAINT_CHECK;
|
||||
r->name = pstrdup(NameStr(c->conname));
|
||||
r->check_expr = check_expr;
|
||||
r->check_expr = copyObject(check_expr);
|
||||
r->check_exprstate = NULL;
|
||||
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
|
||||
Reference in New Issue
Block a user