summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2010-07-23 00:43:09 +0000
committerRobert Haas <rhaas@postgresql.org>2010-07-23 00:43:09 +0000
commitf53eeec2343fbb66c996b98e3006818fdc393f30 (patch)
tree8907620b3c3cb910e24c4fd958813adeebab5686
parentdb64a9d20eeb0d3a52b7fb520a88bc68b73b374b (diff)
Avoid deep recursion when assigning XIDs to multiple levels of subxacts.
Backpatch to 8.0. Andres Freund, with cleanup and adjustment for older branches by me.
-rw-r--r--src/backend/access/transam/xact.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index d125738b4c8..a74727eddd0 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.293 2010/07/06 19:18:55 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.293.2.1 2010/07/23 00:43:09 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -408,10 +408,32 @@ AssignTransactionId(TransactionState s)
/*
* Ensure parent(s) have XIDs, so that a child always has an XID later
- * than its parent.
+ * than its parent. Musn't recurse here, or we might get a stack overflow
+ * if we're at the bottom of a huge stack of subtransactions none of which
+ * have XIDs yet.
*/
if (isSubXact && !TransactionIdIsValid(s->parent->transactionId))
- AssignTransactionId(s->parent);
+ {
+ TransactionState p = s->parent;
+ TransactionState *parents;
+ size_t parentOffset = 0;
+
+ parents = palloc(sizeof(TransactionState) * s->nestingLevel);
+ while (p != NULL && !TransactionIdIsValid(p->transactionId))
+ {
+ parents[parentOffset++] = p;
+ p = p->parent;
+ }
+
+ /*
+ * This is technically a recursive call, but the recursion will
+ * never be more than one layer deep.
+ */
+ while (parentOffset != 0)
+ AssignTransactionId(parents[--parentOffset]);
+
+ pfree(parents);
+ }
/*
* Generate a new Xid and record it in PG_PROC and pg_subtrans.