diff --git a/src/backend/distributed/transaction/distributed_deadlock_detection.c b/src/backend/distributed/transaction/distributed_deadlock_detection.c index 64cbf8307..295456789 100644 --- a/src/backend/distributed/transaction/distributed_deadlock_detection.c +++ b/src/backend/distributed/transaction/distributed_deadlock_detection.c @@ -135,6 +135,12 @@ CheckForDistributedDeadlocks(void) bool deadlockFound = false; List *deadlockPath = NIL; + /* + * Since we only see nodes which are waiting or being waited upon it's not + * possible to have more than edgeCount + 1 nodes. + */ + int maxStackDepth = edgeCount + 1; + /* we're only interested in finding deadlocks originating from this node */ if (transactionNode->transactionId.initiatorNodeIdentifier != localGroupId) { @@ -144,7 +150,7 @@ CheckForDistributedDeadlocks(void) ResetVisitedFields(adjacencyLists); deadlockFound = CheckDeadlockForTransactionNode(transactionNode, - edgeCount, + maxStackDepth, &deadlockPath); if (deadlockFound) { @@ -233,22 +239,24 @@ CheckDeadlockForTransactionNode(TransactionNode *startingTransactionNode, List **deadlockPath) { List *toBeVisitedNodes = NIL; - int currentStackDepth = 0; - TransactionNode *transactionNodeStack[maxStackDepth]; + const int rootStackDepth = 0; + TransactionNode **transactionNodeStack = + palloc0(maxStackDepth * sizeof(TransactionNode *)); /* * We keep transactionNodeStack to keep track of the deadlock paths. At this point, * adjust the depth of the starting node and set the stack's first element with * the starting node. */ - transactionNodeStack[currentStackDepth] = startingTransactionNode; + transactionNodeStack[rootStackDepth] = startingTransactionNode; - PrependOutgoingNodesToQueue(startingTransactionNode, currentStackDepth, + PrependOutgoingNodesToQueue(startingTransactionNode, rootStackDepth, &toBeVisitedNodes); /* traverse the graph and search for the deadlocks */ while (toBeVisitedNodes != NIL) { + int currentStackDepth; QueuedTransactionNode *queuedTransactionNode = (QueuedTransactionNode *) linitial(toBeVisitedNodes); TransactionNode *currentTransactionNode = queuedTransactionNode->transactionNode; @@ -261,6 +269,7 @@ CheckDeadlockForTransactionNode(TransactionNode *startingTransactionNode, BuildDeadlockPathList(queuedTransactionNode, transactionNodeStack, deadlockPath); + pfree(transactionNodeStack); return true; } @@ -274,12 +283,14 @@ CheckDeadlockForTransactionNode(TransactionNode *startingTransactionNode, /* set the stack's corresponding element with the current node */ currentStackDepth = queuedTransactionNode->currentStackDepth; + Assert(currentStackDepth < maxStackDepth); transactionNodeStack[currentStackDepth] = currentTransactionNode; PrependOutgoingNodesToQueue(currentTransactionNode, currentStackDepth, &toBeVisitedNodes); } + pfree(transactionNodeStack); return false; }