mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Avoid memory leakage when a series of subtransactions invoke AFTER triggers
that are fired at end-of-statement (as is the normal case for foreign keys, for example). In this situation the per-subxact deferred trigger context is always empty when subtransaction exit is reached; so we could free it, but were not doing so, leading to an intratransaction leak of 8K or more per subtransaction. Per off-list example from Viatcheslav Kalinin subsequent to bug #3418 (his original bug report omitted a foreign key constraint needed to cause this leak). Back-patch to 8.2; prior versions were not using per-subxact contexts for deferred triggers, so did not have this leak.
This commit is contained in:
parent
beba73763b
commit
8f55b9a8ba
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.214 2007/03/19 23:38:29 wieck Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.215 2007/07/01 17:45:42 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -2814,6 +2814,24 @@ AfterTriggerEndSubXact(bool isCommit)
|
||||
afterTriggers->state_stack[my_level] = NULL;
|
||||
Assert(afterTriggers->query_depth ==
|
||||
afterTriggers->depth_stack[my_level]);
|
||||
/*
|
||||
* It's entirely possible that the subxact created an event_cxt but
|
||||
* there is not anything left in it (because all the triggers were
|
||||
* fired at end-of-statement). If so, we should release the context
|
||||
* to prevent memory leakage in a long sequence of subtransactions.
|
||||
* We can detect whether there's anything of use in the context by
|
||||
* seeing if anything was added to the global events list since
|
||||
* subxact start. (This test doesn't catch every case where the
|
||||
* context is deletable; for instance maybe the only additions were
|
||||
* from a sub-sub-xact. But it handles the common case.)
|
||||
*/
|
||||
if (afterTriggers->cxt_stack[my_level] &&
|
||||
afterTriggers->events.tail == afterTriggers->events_stack[my_level].tail)
|
||||
{
|
||||
MemoryContextDelete(afterTriggers->cxt_stack[my_level]);
|
||||
/* avoid double delete if abort later */
|
||||
afterTriggers->cxt_stack[my_level] = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user