From f5b4bb88120f8945ead702bec0e4eaf46542e8f3 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Sun, 5 Aug 2018 05:32:27 +0900
Subject: [PATCH] Reset properly errno before calling write()

6cb3372 enforces errno to ENOSPC when less bytes than what is expected
have been written when it is unset, though it forgot to properly reset
errno before doing a system call to write(), causing errno to
potentially come from a previous system call.

Reported-by: Tom Lane
Author: Michael Paquier
Reviewed-by: Tom Lane
Discussion: https://postgr.es/m/31797.1533326676@sss.pgh.pa.us
---
 src/backend/access/heap/rewriteheap.c           | 1 +
 src/backend/access/transam/twophase.c           | 1 +
 src/backend/replication/logical/origin.c        | 3 +++
 src/backend/replication/logical/reorderbuffer.c | 1 +
 src/backend/replication/logical/snapbuild.c     | 1 +
 src/backend/replication/slot.c                  | 1 +
 src/bin/pg_basebackup/receivelog.c              | 2 ++
 7 files changed, 10 insertions(+)

diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index e628c9bd89d..bbb04d90e82 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -1162,6 +1162,7 @@ heap_xlog_logical_rewrite(XLogReaderState *r)
 	len = xlrec->num_mappings * sizeof(LogicalRewriteMappingData);
 
 	/* write out tail end of mapping file (again) */
+	errno = 0;
 	if (write(fd, data, len) != len)
 	{
 		/* if write didn't set errno, assume problem is no disk space */
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index a23eed56831..4429dc20083 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -1553,6 +1553,7 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
 						path)));
 
 	/* Write content and CRC */
+	errno = 0;
 	if (write(fd, content, len) != len)
 	{
 		int			save_errno = errno;
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index d6bae6cc897..7b1385968ca 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -547,6 +547,7 @@ CheckPointReplicationOrigin(void)
 						tmppath)));
 
 	/* write magic */
+	errno = 0;
 	if ((write(tmpfd, &magic, sizeof(magic))) != sizeof(magic))
 	{
 		int			save_errno = errno;
@@ -590,6 +591,7 @@ CheckPointReplicationOrigin(void)
 		/* make sure we only write out a commit that's persistent */
 		XLogFlush(local_lsn);
 
+		errno = 0;
 		if ((write(tmpfd, &disk_state, sizeof(disk_state))) !=
 			sizeof(disk_state))
 		{
@@ -612,6 +614,7 @@ CheckPointReplicationOrigin(void)
 
 	/* write out the CRC */
 	FIN_CRC32C(crc);
+	errno = 0;
 	if ((write(tmpfd, &crc, sizeof(crc))) != sizeof(crc))
 	{
 		int			save_errno = errno;
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 47e669578f2..de5d2c6a186 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -2479,6 +2479,7 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
 
 	ondisk->size = sz;
 
+	errno = 0;
 	if (write(fd, rb->outbuf, ondisk->size) != ondisk->size)
 	{
 		int			save_errno = errno;
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index 77997ec2e35..d8d8f03cdf9 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1588,6 +1588,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
 		ereport(ERROR,
 				(errmsg("could not open file \"%s\": %m", path)));
 
+	errno = 0;
 	if ((write(fd, ondisk, needed_length)) != needed_length)
 	{
 		int			save_errno = errno;
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 59b0d846226..62cdf2d9eac 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -1080,6 +1080,7 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel)
 				SnapBuildOnDiskChecksummedSize);
 	FIN_CRC32C(cp.checksum);
 
+	errno = 0;
 	if ((write(fd, &cp, sizeof(cp))) != sizeof(cp))
 	{
 		int			save_errno = errno;
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index c9fb4198b07..79072a7939a 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -147,6 +147,7 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
 	zerobuf = pg_malloc0(XLOG_BLCKSZ);
 	for (bytes = 0; bytes < XLogSegSize; bytes += XLOG_BLCKSZ)
 	{
+		errno = 0;
 		if (write(f, zerobuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
 		{
 			/* if write didn't set errno, assume problem is no disk space */
@@ -1189,6 +1190,7 @@ ProcessXLogDataMsg(PGconn *conn, StreamCtl *stream, char *copybuf, int len,
 			}
 		}
 
+		errno = 0;
 		if (write(walfile,
 				  copybuf + hdr_len + bytes_written,
 				  bytes_to_write) != bytes_to_write)
-- 
GitLab