From a66fede89c21bf6c6737581d1baf177047ad8a83 Mon Sep 17 00:00:00 2001 From: Mark Dilger 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)