diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-07-01 17:45:49 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-07-01 17:45:49 +0000 |
commit | b60765944d60abab22a9f15e63671efecb9748f2 (patch) | |
tree | a537a87666f14a615896734a29dc49118a8f1e86 /src/backend/commands/trigger.c | |
parent | f6eafabc6e66f946707ff5d29078889863382778 (diff) | |
download | postgresql-b60765944d60abab22a9f15e63671efecb9748f2.tar.gz postgresql-b60765944d60abab22a9f15e63671efecb9748f2.zip |
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.
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r-- | src/backend/commands/trigger.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 2f602d742e2..30b4ecbab63 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.210.2.1 2007/01/25 04:17:56 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.210.2.2 2007/07/01 17:45:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2766,6 +2766,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 { |