From f911b75aa0fadc44241cd1d721b59f4c7fa3d549 Mon Sep 17 00:00:00 2001
From: Kuntal Ghosh <kuntal.ghosh@enterprisedb.com>
Date: Fri, 7 Feb 2020 17:18:12 +0530
Subject: [PATCH] Restrict memory allocation in reorderbuffer context

Once we have allocated memory required to build the slab cache, we don't
have to allocate memory of MaxHeapTupleSize although its size is much
lesser than that.  Otherwise, this can lead to a OOM failure very
quickly.
---
 src/backend/replication/logical/reorderbuffer.c | 10 +++++++++-
 src/include/replication/reorderbuffer.h         |  1 +
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index c970324b63..65ddd41612 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -259,6 +259,7 @@ ReorderBufferAllocate(void)
 	buffer->by_txn_last_txn = NULL;
 
 	buffer->nr_cached_tuplebufs = 0;
+	buffer->nr_allocated_tuplebufs = 0;
 
 	buffer->outbuf = NULL;
 	buffer->outbufsize = 0;
@@ -424,8 +425,13 @@ ReorderBufferGetTupleBuf(ReorderBuffer *rb, Size tuple_len)
 	 * those. Thus always allocate at least MaxHeapTupleSize. Note that tuples
 	 * generated for oldtuples can be bigger, as they don't have out-of-line
 	 * toast columns.
+	 *
+	 * But, if we've already allocated the memory required for building the
+	 * cache later, we don't have to allocate memory more than the size of the
+	 * tuple.
 	 */
-	if (alloc_len < MaxHeapTupleSize)
+	if (alloc_len < MaxHeapTupleSize &&
+		rb->nr_allocated_tuplebufs < max_cached_tuplebufs)
 		alloc_len = MaxHeapTupleSize;
 
 
@@ -448,6 +454,7 @@ ReorderBufferGetTupleBuf(ReorderBuffer *rb, Size tuple_len)
 	}
 	else
 	{
+		rb->nr_allocated_tuplebufs++;
 		tuple = (ReorderBufferTupleBuf *)
 			MemoryContextAlloc(rb->context,
 							   sizeof(ReorderBufferTupleBuf) +
@@ -481,6 +488,7 @@ ReorderBufferReturnTupleBuf(ReorderBuffer *rb, ReorderBufferTupleBuf *tuple)
 	}
 	else
 	{
+		rb->nr_allocated_tuplebufs--;
 		pfree(tuple);
 	}
 }
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index 86effe106b..a1799dbb29 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -358,6 +358,7 @@ struct ReorderBuffer
 	/* cached ReorderBufferTupleBufs */
 	slist_head	cached_tuplebufs;
 	Size		nr_cached_tuplebufs;
+	Size		nr_allocated_tuplebufs;
 
 	XLogRecPtr	current_restart_decoding_lsn;
 
-- 
2.17.1

