From 16ee6eaf80a40007a138b60bb5661660058d0422 Mon Sep 17 00:00:00 2001
From: Noah Misch <noah@leadboat.com>
Date: Wed, 3 Apr 2019 23:16:37 -0700
Subject: [PATCH] Make src/test/recovery/t/017_shm.pl safe for concurrent
 execution.

Buildfarm members idiacanthus and komodoensis, which share a host, both
executed this test in the same second.  That failed.  Back-patch to 9.6,
where the test first appeared.

Discussion: https://postgr.es/m/20190404020543.GA1319573@rfd.leadboat.com
---
 src/test/recovery/t/017_shm.pl | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/src/test/recovery/t/017_shm.pl b/src/test/recovery/t/017_shm.pl
index 902156269f..8e85d6b7cd 100644
--- a/src/test/recovery/t/017_shm.pl
+++ b/src/test/recovery/t/017_shm.pl
@@ -13,11 +13,6 @@ plan tests => 6;
 my $tempdir = TestLib::tempdir;
 my $port;
 
-# When using Unix sockets, we can dictate the port number.  In the absence of
-# collisions from other shmget() activity, gnat starts with key 0x7d001
-# (512001), and flea starts with key 0x7d002 (512002).
-$port = 512 unless $PostgresNode::use_tcp;
-
 # Log "ipcs" diffs on a best-effort basis, swallowing any error.
 my $ipcs_before = "$tempdir/ipcs_before";
 eval { run_log [ 'ipcs', '-am' ], '>', $ipcs_before; };
@@ -28,6 +23,33 @@ sub log_ipcs
 	return;
 }
 
+# With Unix sockets, choose a port number such that the port number's first
+# IpcMemoryKey candidate is available.  If multiple copies of this test run
+# concurrently, they will pick different ports.  In the absence of collisions
+# from other shmget() activity, gnat starts with key 0x7d001 (512001), and
+# flea starts with key 0x7d002 (512002).  With TCP, the first get_new_node
+# picks a port number.
+my $port_holder;
+if (!$PostgresNode::use_tcp)
+{
+	for ($port = 512; $port < 612; ++$port)
+	{
+		$port_holder = PostgresNode->get_new_node(
+			"port${port}_holder",
+			port     => $port,
+			own_host => 1);
+		$port_holder->init;
+		$port_holder->start;
+		# Match the AddToDataDirLockFile() call in sysv_shmem.c.  Assume all
+		# systems not using sysv_shmem.c do use TCP.
+		my $shmem_key_line_prefix = sprintf("%9lu ", 1 + $port * 1000);
+		last
+		  if slurp_file($port_holder->data_dir . '/postmaster.pid') =~
+		  /^$shmem_key_line_prefix/m;
+		$port_holder->stop;
+	}
+}
+
 # Node setup.
 sub init_start
 {
@@ -125,6 +147,7 @@ poll_start($gnat);       # recycle second key
 
 $gnat->stop;
 $flea->stop;
+$port_holder->stop if $port_holder;
 log_ipcs();
 
 
-- 
2.40.0