From 6dc886922ddd12ca4bc2b40bb340ffc6a188ffad Mon Sep 17 00:00:00 2001
From: vignesh <vignesh@localhost.localdomain>
Date: Wed, 11 Dec 2019 10:37:40 +0530
Subject: [PATCH] Reorder buffer crash while aborting old transactions.

While aborting aborted transactions it crashed as there are no reorderbuffer
changes present in the list because all the reorderbuffer changes were
serialized. Fixing it by storing the last change's lsn while serializing the
reorderbuffer changes. This lsn will be used as final_lsn in scenarios where
all the reorder buffer change list is serialized.
---
 src/backend/replication/logical/reorderbuffer.c | 19 ++++++++++++++++++-
 src/include/replication/reorderbuffer.h         |  8 ++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 53affeb..0122bdb 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -1963,13 +1963,22 @@ ReorderBufferAbortOld(ReorderBuffer *rb, TransactionId oldestRunningXid)
 			 * final_lsn to that of their last change; this causes
 			 * ReorderBufferRestoreCleanup to do the right thing.
 			 */
-			if (txn->serialized && txn->final_lsn == 0)
+			if (txn->serialized && txn->final_lsn == 0 &&
+				!dlist_is_empty(&txn->changes))
 			{
 				ReorderBufferChange *last =
 				dlist_tail_element(ReorderBufferChange, node, &txn->changes);
 
 				txn->final_lsn = last->lsn;
 			}
+			else
+			{
+				/*
+				 * There are no changes present as all of the changes were
+				 * serialized, use the last lsn that was serialized.
+				 */
+				txn->final_lsn = txn->last_serialized_lsn;
+			}
 
 			elog(DEBUG2, "aborting old transaction %u", txn->xid);
 
@@ -2433,6 +2442,14 @@ ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
 		ReorderBufferSerializeTXN(rb, subtxn);
 	}
 
+	if (!dlist_is_empty(&txn->changes))
+	{
+		ReorderBufferChange *lastChange =
+		dlist_tail_element(ReorderBufferChange,	node, &txn->changes);
+
+		txn->last_serialized_lsn = lastChange->lsn;
+	}
+
 	/* serialize changestream */
 	dlist_foreach_modify(change_i, &txn->changes)
 	{
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index 0867ee9..dbf3c7d 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -247,6 +247,14 @@ typedef struct ReorderBufferTXN
 	bool		serialized;
 
 	/*
+	 * The last lsn that is serialized, this is required to generate the
+	 * serialized file and removing them while aborting old transactions when
+	 * there are no changes present in memory as all of the changes have been
+	 * serialized.
+	 */
+	XLogRecPtr	last_serialized_lsn;
+
+	/*
 	 * List of ReorderBufferChange structs, including new Snapshots and new
 	 * CommandIds
 	 */
-- 
1.8.3.1

