summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2010-07-23 00:43:35 +0000
committerRobert Haas <rhaas@postgresql.org>2010-07-23 00:43:35 +0000
commitae1b65b5aa17ab96f95f34d258b1cb358f1d9030 (patch)
tree78782653b266c9a8d5eb60ef9a05e04252f589fb
parent49d7a64f60425c56fa331e2fee99aa7967abc847 (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.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 583f55ddae6..0ec504d26be 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.229.2.7 2010/01/24 21:49:47 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.229.2.8 2010/07/23 00:43:35 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -351,8 +351,35 @@ AssignSubTransactionId(TransactionState s)
Assert(s->parent != NULL);
Assert(s->state == TRANS_INPROGRESS);
+
+ /*
+ * Ensure parent(s) have XIDs, so that a child always has an XID later
+ * 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 (!TransactionIdIsValid(s->parent->transactionId))
- AssignSubTransactionId(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)
+ AssignSubTransactionId(parents[--parentOffset]);
+
+ pfree(parents);
+ }
/*
* Generate a new Xid and record it in PG_PROC and pg_subtrans.