From 6d8ca934e86e63c3e867ecef355bd373412f6b6a Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 19 Jul 2010 19:44:45 +0200
Subject: [PATCH] Don't segfault upon too deeply nested subtransactions.

Build a list of parent transactions and iterate it in the correct
order instead of using recursion to avoid a stack overflow.
---
 src/backend/access/transam/xact.c |   24 ++++++++++++++++++++++--
 1 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 6ba6534..be0b448 100644
*** a/src/backend/access/transam/xact.c
--- b/src/backend/access/transam/xact.c
*************** AssignTransactionId(TransactionState s)
*** 409,417 ****
  	/*
  	 * Ensure parent(s) have XIDs, so that a child always has an XID later
  	 * than its parent.
  	 */
! 	if (isSubXact && !TransactionIdIsValid(s->parent->transactionId))
! 		AssignTransactionId(s->parent);
  
  	/*
  	 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
--- 409,437 ----
  	/*
  	 * Ensure parent(s) have XIDs, so that a child always has an XID later
  	 * than its parent.
+ 	 * We don't use recursion here to allow arbitrarily deep nesting.
  	 */
! 	if(isSubXact && !TransactionIdIsValid(s->parent->transactionId)){
! 		TransactionState p = s->parent;
! 		TransactionState* parents;
! 		size_t parentOffset = 0;
! 
! 		parents = palloc(sizeof(TransactionState) *  s->nestingLevel);
! 
! 		while(p && !TransactionIdIsValid(p->transactionId)){
! 			parents[parentOffset++] = p;
! 			p = p->parent;
! 		}
! 
! 		while(parentOffset != 0){
! 			/*
! 			 * Note that this won't recurse because p will never have a
! 			 * parent with an invalid transactionId at that point.
! 			 */
! 			AssignTransactionId(parents[--parentOffset]);
! 		}
! 		pfree(parents);
! 	}
  
  	/*
  	 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
-- 
1.7.2.rc1.10.gae32f

