aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-07-01 17:45:42 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-07-01 17:45:42 +0000
commit8f55b9a8ba6d6543c162927c29f8d06ce1cd7372 (patch)
treee724af0344d9b4b62157b326a96a725a1bff9370 /src/backend/commands/trigger.c
parentbeba73763bbe612d7635eb97a29aa6377e79fa6b (diff)
downloadpostgresql-8f55b9a8ba6d6543c162927c29f8d06ce1cd7372.tar.gz
postgresql-8f55b9a8ba6d6543c162927c29f8d06ce1cd7372.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.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index e2dadb7a7e2..3f251ad6dd5 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.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
{