summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2010-07-23 00:43:44 +0000
committerRobert Haas <rhaas@postgresql.org>2010-07-23 00:43:44 +0000
commit202c89c9d01616a63d35f5d9b4585e7d0b694fa7 (patch)
tree1ef4cf081ec7a3961bc1413768c622d27a8842a0
parentb9ded24614b3209e909014744a553f7b334331f2 (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 33a862c8ef6..562cd39ce87 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.215.2.7 2010/01/24 21:49:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.215.2.8 2010/07/23 00:43:44 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -346,8 +346,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.