commit c617789af9006a1e4716d039b3f1f7fb45ae5227
Author: Hao Wu <gfphoenix78@gmail.com>
Date:   Mon Mar 28 23:06:20 2022 -0700

    Enables to call Unregister*XactCallback() in Call*XactCallback()
    
    It's a natural requirement to unregister the callback for transaction or
    subtransaction when the callback is invoked, so we don't have to
    unregister the callback somewhere. If it's not allowed to do it
    in CallXactCallback() or CallSubXactCallback(), we must handle it
    carefully.
    Luckily, we just need a few lines of code to support this feature,
    by saving the next pointer before calling the callback.

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 3596a7d734..3eda32d3d3 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -3630,9 +3630,13 @@ static void
 CallXactCallbacks(XactEvent event)
 {
 	XactCallbackItem *item;
+	XactCallbackItem *next;
 
-	for (item = Xact_callbacks; item; item = item->next)
+	for (item = Xact_callbacks; item; item = next)
+	{
+		next = item->next;
 		item->callback(event, item->arg);
+	}
 }
 
 
@@ -3687,9 +3691,13 @@ CallSubXactCallbacks(SubXactEvent event,
 					 SubTransactionId parentSubid)
 {
 	SubXactCallbackItem *item;
+	SubXactCallbackItem *next;
 
-	for (item = SubXact_callbacks; item; item = item->next)
+	for (item = SubXact_callbacks; item; item = next)
+	{
+		next = item->next;
 		item->callback(event, mySubid, parentSubid, item->arg);
+	}
 }
 
 
