From a66fede89c21bf6c6737581d1baf177047ad8a83 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Thu, 15 Jul 2021 12:10:54 -0700
Subject: [PATCH v1] No longer ignoring failures on file close

When writing the changes from transactions as part of logical
replication, the transient files to which transaction changes are
written were being closed without checking the return value from
close().  Fix that.

The return code from write() was already being handled reasonably,
but on filesystems which buffer write()s, the attempt to flush the
buffer during the close() operation may fail, with write() returning
-1 and setting errno.  This was not checked, meaning that some or
all of the changes for a transaction could be partially or entirely
missing, resulting in garbled data that cannot be replayed on the
subscriber side, or worse still, silently missing changes.
---
 src/backend/replication/logical/reorderbuffer.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 7378beb684..3d13c42098 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -3552,7 +3552,11 @@ ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
 			char		path[MAXPGPATH];
 
 			if (fd != -1)
-				CloseTransientFile(fd);
+				if (CloseTransientFile(fd))
+					ereport(ERROR,
+							(errcode_for_file_access(),
+							 errmsg("could not close file: %m")));
+
 
 			XLByteToSeg(change->lsn, curOpenSegNo, wal_segment_size);
 
@@ -3599,7 +3603,10 @@ ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
 	txn->txn_flags |= RBTXN_IS_SERIALIZED;
 
 	if (fd != -1)
-		CloseTransientFile(fd);
+		if (CloseTransientFile(fd))
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not close file: %m")));
 }
 
 /*
@@ -3794,7 +3801,7 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
 	{
 		int			save_errno = errno;
 
-		CloseTransientFile(fd);
+		(void) CloseTransientFile(fd);	/* no error checking */
 
 		/* if write didn't set errno, assume problem is no disk space */
 		errno = save_errno ? save_errno : ENOSPC;
-- 
2.21.1 (Apple Git-122.3)

