From 9e3ead04bf86a3e0fd9e16a7c823e2f7335337ff Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@bowt.ie>
Date: Wed, 21 Feb 2018 11:57:56 -0800
Subject: [PATCH] Avoid another Valgrind complaint about a logtape.c write().

LogicalTapeRewindForRead() may write out its first block when it is
dirty but not full, just like LogicalTapeFreeze().  To avoid Valgrind
complaints, tell it to treat the tail of logtape.c's buffer as defined
within LogicalTapeRewindForRead().  This is a mechanical duplication of
the code from commit 9fafa413ac602624e10f61ef44a20c17029d43d8.

Valgrind complained inconsistently when isolation tests are run because
the precise scheduling of worker processes affects whether or not
uninitialized/poisoned bytes can be flushed in the
LogicalTapeRewindForRead() path.  There has to be enough tuples for a
worker to need to spill and merge multiple runs, and yet not so many
that even a BLCKSZ buffer is filled.  This is just barely possible.

Per buildfarm member skink.  It's not completely clear that this will
fix the issue, since it's hard to reproduce, but let's see what the
buildfarm thinks of it.

Peter Geoghegan
---
 src/backend/utils/sort/logtape.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c
index d6794bf..05dde63 100644
--- a/src/backend/utils/sort/logtape.c
+++ b/src/backend/utils/sort/logtape.c
@@ -739,6 +739,18 @@ LogicalTapeRewindForRead(LogicalTapeSet *lts, int tapenum, size_t buffer_size)
 		 */
 		if (lt->dirty)
 		{
+			/*
+			 * As long as we've filled the buffer at least once, its contents
+			 * are entirely defined from valgrind's point of view, even though
+			 * contents beyond the current end point may be stale.  But it's
+			 * possible - at least in the case of a parallel sort - to sort
+			 * such small amount of data that we do not fill the buffer even
+			 * once.  Tell valgrind that its contents are defined, so it
+			 * doesn't bleat.
+			 */
+			VALGRIND_MAKE_MEM_DEFINED(lt->buffer + lt->nbytes,
+									  lt->buffer_size - lt->nbytes);
+
 			TapeBlockSetNBytes(lt->buffer, lt->nbytes);
 			ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
 		}
-- 
2.7.4

