From 138b5f06d1a55a03561f9fd98971e5b6c3dbf377 Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Date: Mon, 2 Nov 2026 13:43:46 +0900
Subject: [PATCH v2 1/3] Stabilize 051_effective_wal_level

---
 .../recovery/t/051_effective_wal_level.pl     | 43 ++++++++++++++++---
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/src/test/recovery/t/051_effective_wal_level.pl b/src/test/recovery/t/051_effective_wal_level.pl
index 4aa26ec786b..adb7555ae76 100644
--- a/src/test/recovery/t/051_effective_wal_level.pl
+++ b/src/test/recovery/t/051_effective_wal_level.pl
@@ -32,6 +32,19 @@ sub wait_for_logical_decoding_disabled
 		qq[select current_setting('effective_wal_level') = 'replica';]);
 }
 
+# Close a background psql session and wait for its server backend to finish
+# exit processing so that its local injection point names can be safely reused.
+sub quit_and_wait_for_backend
+{
+	my ($node, $background_psql, $backend_pid) = @_;
+
+	die "invalid backend PID: $backend_pid" unless $backend_pid =~ /^\d+$/;
+	$background_psql->quit;
+	$node->poll_query_until('postgres',
+		qq[select count(*) = 0 from pg_stat_activity where pid = $backend_pid])
+	  or die "timed out waiting for backend $backend_pid to exit";
+}
+
 # Initialize the primary server with wal_level = 'replica'.
 my $primary = PostgreSQL::Test::Cluster->new('primary');
 $primary->init(allows_streaming => 1);
@@ -416,6 +429,8 @@ if (   $ENV{enable_injection_points} eq 'yes'
 
 	# Start a psql session and stop it in the middle of the activation process.
 	my $psql_create_slot = $primary->background_psql('postgres');
+	my $psql_create_slot_pid =
+	  $psql_create_slot->query_safe('select pg_backend_pid()', verbose => 0);
 	$psql_create_slot->query_until(
 		qr/create_slot_1/,
 		q(\echo create_slot_1
@@ -443,7 +458,8 @@ select pg_create_logical_replication_slot('slot_1', 'test_decoding');
 		qq[select injection_points_wakeup('logical-decoding-activation')]);
 
 	# Let the released backend finish creating its slot.
-	$psql_create_slot->quit;
+	quit_and_wait_for_backend($primary, $psql_create_slot,
+		$psql_create_slot_pid);
 
 	# Decode from slot_2, whose start point precedes where a redundant
 	# status-change record would have been written; this fails in xlog_decode()
@@ -470,6 +486,8 @@ select pg_drop_replication_slot('slot_2');
 	# interrupted.
 	$psql_create_slot =
 	  $primary->background_psql('postgres', on_error_stop => 0);
+	$psql_create_slot_pid =
+	  $psql_create_slot->query_safe('select pg_backend_pid()', verbose => 0);
 
 	# Start the logical decoding activation process upon creating the logical
 	# slot, but it will wait due to the injection point.
@@ -497,11 +515,14 @@ select pg_cancel_backend(pid) from pg_stat_activity where query ~ 'slot_canceled
 	wait_for_logical_decoding_disabled($primary);
 	pass("the activation process aborted");
 
-	$psql_create_slot->quit;
+	quit_and_wait_for_backend($primary, $psql_create_slot,
+		$psql_create_slot_pid);
 
 	# Test concurrent activation processes run and one is interrupted.
 	$psql_create_slot =
 	  $primary->background_psql('postgres', on_error_stop => 0);
+	$psql_create_slot_pid =
+	  $psql_create_slot->query_safe('select pg_backend_pid()', verbose => 0);
 
 	# Start a psql session and stops in the middle of the activation
 	# process.
@@ -540,7 +561,8 @@ select pg_cancel_backend(pid) from pg_stat_activity where query ~ 'slot_canceled
 		"effective_wal_level remains 'logical' even after the concurrent activation is interrupted"
 	);
 
-	$psql_create_slot->quit;
+	quit_and_wait_for_backend($primary, $psql_create_slot,
+		$psql_create_slot_pid);
 
 	# Test races between the deactivation of logical decoding and slot
 	# creation during recovery. Logical decoding can be deactivated while a
@@ -596,6 +618,8 @@ hot_standby_feedback = on
 	# information but before creating the local slot.  Note that this point
 	# waits when reaching the creation of slot "sync_slot".
 	my $psql_sync_slot = $standby5->background_psql('postgres');
+	my $psql_sync_slot_pid =
+	  $psql_sync_slot->query_safe('select pg_backend_pid()', verbose => 0);
 	$psql_sync_slot->query_until(
 		qr/sync_slots/,
 		q(\echo sync_slots
@@ -622,7 +646,8 @@ select pg_sync_replication_slots();
 		qq[select injection_points_wakeup('replication-slot-create-begin')]);
 	$standby5->wait_for_log(
 		qr/could not synchronize replication slot "sync_slot"/, $log_offset);
-	$psql_sync_slot->quit;
+	quit_and_wait_for_backend($standby5, $psql_sync_slot,
+		$psql_sync_slot_pid);
 	is( $standby5->safe_psql(
 			'postgres', qq[select count(*) from pg_replication_slots]),
 		'0',
@@ -643,6 +668,8 @@ select pg_sync_replication_slots();
 	);
 
 	$psql_sync_slot = $standby5->background_psql('postgres');
+	$psql_sync_slot_pid =
+	  $psql_sync_slot->query_safe('select pg_backend_pid()', verbose => 0);
 	$psql_sync_slot->query_until(
 		qr/sync_slots/,
 		q(\echo sync_slots
@@ -696,7 +723,8 @@ select pg_create_logical_replication_slot('test_slot4', 'test_decoding');
 select pg_drop_replication_slot('sync_slot');
 ]);
 	$primary->wait_for_replay_catchup($standby5);
-	$psql_sync_slot->quit;
+	quit_and_wait_for_backend($standby5, $psql_sync_slot,
+		$psql_sync_slot_pid);
 
 	# The slot created on retry may or may not have been persisted by the
 	# time the remote slot was dropped. One more synchronization cycle
@@ -734,6 +762,8 @@ select pg_drop_replication_slot('sync_slot');
 	# Start creating a logical slot, stopping it before creating the slot.
 	$psql_create_slot =
 	  $standby5->background_psql('postgres', on_error_stop => 0);
+	$psql_create_slot_pid =
+	  $psql_create_slot->query_safe('select pg_backend_pid()', verbose => 0);
 	# Note that this point waits when reaching the creation of slot
 	# "standby5_slot".
 	$psql_create_slot->query_until(
@@ -761,7 +791,8 @@ select pg_create_logical_replication_slot('standby5_slot', 'test_decoding');
 	$standby5->wait_for_log(
 		qr/ERROR: .* logical decoding on standby requires "effective_wal_level" >= "logical" on the primary/,
 		$log_offset);
-	$psql_create_slot->quit;
+	quit_and_wait_for_backend($standby5, $psql_create_slot,
+		$psql_create_slot_pid);
 	is( $standby5->safe_psql(
 			'postgres', qq[select count(*) from pg_replication_slots]),
 		'0',
-- 
2.52.0

