diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index df5a67e4c31..8870d1f961e 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -346,8 +346,8 @@ static void CommitTransaction(void);
 static TransactionId RecordTransactionAbort(bool isSubXact);
 static void StartTransaction(void);
 
-static void CommitTransactionCommandInternal(void);
-static void AbortCurrentTransactionInternal(void);
+static bool CommitTransactionCommandInternal(void);
+static bool AbortCurrentTransactionInternal(void);
 
 static void StartSubTransaction(void);
 static void CommitSubTransaction(void);
@@ -3092,33 +3092,7 @@ RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
 void
 CommitTransactionCommand(void)
 {
-	while (true)
-	{
-		switch (CurrentTransactionState->blockState)
-		{
-				/*
-				 * The current already-failed subtransaction is ending due to
-				 * a ROLLBACK or ROLLBACK TO command, so pop it and
-				 * recursively examine the parent (which could be in any of
-				 * several states).
-				 */
-			case TBLOCK_SUBABORT_END:
-				CleanupSubTransaction();
-				continue;
-
-				/*
-				 * As above, but it's not dead yet, so abort first.
-				 */
-			case TBLOCK_SUBABORT_PENDING:
-				AbortSubTransaction();
-				CleanupSubTransaction();
-				continue;
-			default:
-				break;
-		}
-		CommitTransactionCommandInternal();
-		break;
-	}
+	while (!CommitTransactionCommandInternal());
 }
 
 /*
@@ -3126,16 +3100,12 @@ CommitTransactionCommand(void)
  *		regarding handling the commit transaction command except for loop over
  *		subtransactions.
  */
-static void
+static bool
 CommitTransactionCommandInternal(void)
 {
 	TransactionState s = CurrentTransactionState;
 	SavedTransactionCharacteristics savetc;
 
-	/* This states are handled in CommitTransactionCommand() */
-	Assert(s->blockState != TBLOCK_SUBABORT_END &&
-		   s->blockState != TBLOCK_SUBABORT_PENDING);
-
 	/* Must save in case we need to restore below */
 	SaveTransactionCharacteristics(&savetc);
 
@@ -3376,10 +3346,31 @@ CommitTransactionCommandInternal(void)
 				s->blockState = TBLOCK_SUBINPROGRESS;
 			}
 			break;
+
+			/*
+			 * The current already-failed subtransaction is ending due to
+			 * a ROLLBACK or ROLLBACK TO command, so pop it and
+			 * recursively examine the parent (which could be in any of
+			 * several states).
+			 */
+		case TBLOCK_SUBABORT_END:
+			CleanupSubTransaction();
+			return false;
+
+			/*
+			 * As above, but it's not dead yet, so abort first.
+				*/
+		case TBLOCK_SUBABORT_PENDING:
+			AbortSubTransaction();
+			CleanupSubTransaction();
+			return false;
+
 		default:
 			/* Keep compiler quiet */
 			break;
 	}
+
+	return true;
 }
 
 /*
@@ -3390,38 +3381,7 @@ CommitTransactionCommandInternal(void)
 void
 AbortCurrentTransaction(void)
 {
-	while (true)
-	{
-		switch (CurrentTransactionState->blockState)
-		{
-				/*
-				 * If we failed while trying to create a subtransaction, clean
-				 * up the broken subtransaction and abort the parent.  The
-				 * same applies if we get a failure while ending a
-				 * subtransaction.
-				 */
-			case TBLOCK_SUBBEGIN:
-			case TBLOCK_SUBRELEASE:
-			case TBLOCK_SUBCOMMIT:
-			case TBLOCK_SUBABORT_PENDING:
-			case TBLOCK_SUBRESTART:
-				AbortSubTransaction();
-				CleanupSubTransaction();
-				continue;
-
-				/*
-				 * Same as above, except the Abort() was already done.
-				 */
-			case TBLOCK_SUBABORT_END:
-			case TBLOCK_SUBABORT_RESTART:
-				CleanupSubTransaction();
-				continue;
-			default:
-				break;
-		}
-		AbortCurrentTransactionInternal();
-		break;
-	}
+	while (!AbortCurrentTransactionInternal());
 }
 
 /*
@@ -3429,20 +3389,11 @@ AbortCurrentTransaction(void)
  *		regarding handling the abort transaction command except for loop over
  *		subtransactions.
  */
-static void
+static bool
 AbortCurrentTransactionInternal(void)
 {
 	TransactionState s = CurrentTransactionState;
 
-	/* This states are handled in AbortCurrentTransaction() */
-	Assert(s->blockState != TBLOCK_SUBBEGIN &&
-		   s->blockState != TBLOCK_SUBRELEASE &&
-		   s->blockState != TBLOCK_SUBCOMMIT &&
-		   s->blockState != TBLOCK_SUBABORT_PENDING &&
-		   s->blockState != TBLOCK_SUBRESTART &&
-		   s->blockState != TBLOCK_SUBABORT_END &&
-		   s->blockState != TBLOCK_SUBABORT_RESTART);
-
 	switch (s->blockState)
 	{
 		case TBLOCK_DEFAULT:
@@ -3563,10 +3514,36 @@ AbortCurrentTransactionInternal(void)
 			AbortSubTransaction();
 			s->blockState = TBLOCK_SUBABORT;
 			break;
+
+			/*
+			 * If we failed while trying to create a subtransaction, clean
+			 * up the broken subtransaction and abort the parent.  The
+			 * same applies if we get a failure while ending a
+			 * subtransaction.
+			 */
+		case TBLOCK_SUBBEGIN:
+		case TBLOCK_SUBRELEASE:
+		case TBLOCK_SUBCOMMIT:
+		case TBLOCK_SUBABORT_PENDING:
+		case TBLOCK_SUBRESTART:
+			AbortSubTransaction();
+			CleanupSubTransaction();
+			return false;
+
+			/*
+			 * Same as above, except the Abort() was already done.
+			 */
+		case TBLOCK_SUBABORT_END:
+		case TBLOCK_SUBABORT_RESTART:
+			CleanupSubTransaction();
+			return false;
+
 		default:
 			/* Keep compiler quiet */
 			break;
 	}
+
+	return true;
 }
 
 /*
