From 7124e64520834cd238c9f0efcfe429c28696b11d Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Sun, 5 Aug 2018 05:32:12 +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/walmethods.c              | 6 ++++++
 7 files changed, 14 insertions(+)

diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 601efa089d0..b30fcba726c 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -1167,6 +1167,7 @@ heap_xlog_logical_rewrite(XLogReaderState *r)
 	len = xlrec->num_mappings * sizeof(LogicalRewriteMappingData);
 
 	/* write out tail end of mapping file (again) */
+	errno = 0;
 	pgstat_report_wait_start(WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE);
 	if (write(fd, data, len) != len)
 	{
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 1482fb4c958..29ae6b4ba94 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -1599,6 +1599,7 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
 						path)));
 
 	/* Write content and CRC */
+	errno = 0;
 	pgstat_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_WRITE);
 	if (write(fd, content, len) != len)
 	{
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index f911b651493..c554b05e1a0 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -577,6 +577,7 @@ CheckPointReplicationOrigin(void)
 						tmppath)));
 
 	/* write magic */
+	errno = 0;
 	if ((write(tmpfd, &magic, sizeof(magic))) != sizeof(magic))
 	{
 		int			save_errno = errno;
@@ -620,6 +621,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))
 		{
@@ -642,6 +644,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 69ae504d78c..c2c4dee7808 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -2426,6 +2426,7 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
 
 	ondisk->size = sz;
 
+	errno = 0;
 	pgstat_report_wait_start(WAIT_EVENT_REORDER_BUFFER_WRITE);
 	if (write(fd, rb->outbuf, ondisk->size) != ondisk->size)
 	{
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index b68682a37ff..8549cd506df 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1610,6 +1610,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
 		ereport(ERROR,
 				(errmsg("could not open file \"%s\": %m", path)));
 
+	errno = 0;
 	pgstat_report_wait_start(WAIT_EVENT_SNAPBUILD_WRITE);
 	if ((write(fd, ondisk, needed_length)) != needed_length)
 	{
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index bb9a24ec08d..17e00c4d5c6 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -1269,6 +1269,7 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel)
 				SnapBuildOnDiskChecksummedSize);
 	FIN_CRC32C(cp.checksum);
 
+	errno = 0;
 	pgstat_report_wait_start(WAIT_EVENT_REPLICATION_SLOT_WRITE);
 	if ((write(fd, &cp, sizeof(cp))) != sizeof(cp))
 	{
diff --git a/src/bin/pg_basebackup/walmethods.c b/src/bin/pg_basebackup/walmethods.c
index 82cbf870025..870b6d085e8 100644
--- a/src/bin/pg_basebackup/walmethods.c
+++ b/src/bin/pg_basebackup/walmethods.c
@@ -121,6 +121,7 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		zerobuf = pg_malloc0(XLOG_BLCKSZ);
 		for (bytes = 0; bytes < pad_to_size; bytes += XLOG_BLCKSZ)
 		{
+			errno = 0;
 			if (write(fd, zerobuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
 			{
 				int			save_errno = errno;
@@ -444,6 +445,7 @@ tar_write_compressed_data(void *buf, size_t count, bool flush)
 		{
 			size_t		len = ZLIB_OUT_SIZE - tar_data->zp->avail_out;
 
+			errno = 0;
 			if (write(tar_data->fd, tar_data->zlibOut, len) != len)
 			{
 				/*
@@ -627,6 +629,7 @@ tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 
 	if (!tar_data->compression)
 	{
+		errno = 0;
 		if (write(tar_data->fd, tar_data->currentfile->header, 512) != 512)
 		{
 			save_errno = errno;
@@ -827,6 +830,7 @@ tar_close(Walfile f, WalCloseMethod method)
 		return -1;
 	if (!tar_data->compression)
 	{
+		errno = 0;
 		if (write(tar_data->fd, tf->header, 512) != 512)
 		{
 			/* if write didn't set errno, assume problem is no disk space */
@@ -899,6 +903,7 @@ tar_finish(void)
 	MemSet(zerobuf, 0, sizeof(zerobuf));
 	if (!tar_data->compression)
 	{
+		errno = 0;
 		if (write(tar_data->fd, zerobuf, sizeof(zerobuf)) != sizeof(zerobuf))
 		{
 			/* if write didn't set errno, assume problem is no disk space */
@@ -931,6 +936,7 @@ tar_finish(void)
 			{
 				size_t		len = ZLIB_OUT_SIZE - tar_data->zp->avail_out;
 
+				errno = 0;
 				if (write(tar_data->fd, tar_data->zlibOut, len) != len)
 				{
 					/*
-- 
GitLab