From d30416a303cf78639f71a3d192aa14116da28d4e Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Date: Mon, 18 Aug 2025 11:47:43 +0900
Subject: [PATCH v7 1/2] Set ReplicationSlot::active_pid even in single-user
 mode

Slot manipulation functions except drop could be failed in single-user mode, because
active_pid was not set. Actually the attribute is no-op in the mode but fix the
inconsisntency anyway.
---
 src/backend/replication/slot.c                |  2 +-
 src/test/modules/test_misc/meson.build        |  1 +
 .../t/008_slots_in_single_user_mode.pl        | 73 +++++++++++++++++++
 src/test/recovery/meson.build                 |  2 +-
 4 files changed, 76 insertions(+), 2 deletions(-)
 create mode 100644 src/test/modules/test_misc/t/008_slots_in_single_user_mode.pl

diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 8605776ad86..fd0fdb96d42 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -653,7 +653,7 @@ retry:
 	}
 	else
 	{
-		active_pid = MyProcPid;
+		s->active_pid = active_pid = MyProcPid;
 		ReplicationSlotSetInactiveSince(s, 0, true);
 	}
 	LWLockRelease(ReplicationSlotControlLock);
diff --git a/src/test/modules/test_misc/meson.build b/src/test/modules/test_misc/meson.build
index 9c50de7efb0..08357d2f2e8 100644
--- a/src/test/modules/test_misc/meson.build
+++ b/src/test/modules/test_misc/meson.build
@@ -16,6 +16,7 @@ tests += {
       't/005_timeouts.pl',
       't/006_signal_autovacuum.pl',
       't/007_catcache_inval.pl',
+      't/008_slots_in_single_user_mode.pl',
     ],
   },
 }
diff --git a/src/test/modules/test_misc/t/008_slots_in_single_user_mode.pl b/src/test/modules/test_misc/t/008_slots_in_single_user_mode.pl
new file mode 100644
index 00000000000..4d15efd71ae
--- /dev/null
+++ b/src/test/modules/test_misc/t/008_slots_in_single_user_mode.pl
@@ -0,0 +1,73 @@
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+# Tests the slot manipulation in the single-user mode
+
+# Skip the whole thing on the windows platform
+if ($windows_os)
+{
+	plan skip_all => 'this test is not supported by this platform';
+}
+
+# Run passed commands in single-user mode. The return value from the command is
+# passed through.
+sub run_test_in_single_user_mode
+{
+	my ($node, $commands, $testname) = @_;
+
+	my $result = run_log(
+		[
+			'postgres', '--single', '-F',
+			'-c' => 'exit_on_error=true',
+			'-D' => $node->data_dir,
+			'postgres'
+		],
+		\$commands);
+
+	ok($result, $testname);
+}
+
+my $slotname = 'test_slot';
+
+# Initialize a node
+my $node = PostgreSQL::Test::Cluster->new('node');
+$node->init(allows_streaming => "logical");
+$node->start;
+
+# Define initial table
+$node->safe_psql('postgres', "CREATE TABLE foo (id int)");
+
+# Stop the node to run and test in single-user mode
+$node->stop;
+
+run_test_in_single_user_mode(
+	$node,
+	"SELECT pg_create_logical_replication_slot('$slotname', 'test_decoding')",
+	"replication slot can be created in single-user mode");
+
+run_test_in_single_user_mode(
+	$node, qq(
+INSERT INTO foo VALUES (1);
+SELECT count(1) FROM pg_logical_slot_get_changes('$slotname', NULL, NULL);
+),
+	"logical decoding be done in single-user mode");
+
+run_test_in_single_user_mode(
+	$node,
+	"SELECT pg_replication_slot_advance('$slotname', pg_current_wal_lsn())",
+	"replication slot can be advanced in single-user mode");
+
+run_test_in_single_user_mode(
+	$node,
+	"SELECT pg_copy_logical_replication_slot('$slotname', 'dest_slot')",
+	"replication slot can be copied in single-user mode");
+
+run_test_in_single_user_mode(
+	$node,
+	"SELECT pg_drop_replication_slot('$slotname')",
+	"replication slot can be dropped in single-user mode");
+
+done_testing();
diff --git a/src/test/recovery/meson.build b/src/test/recovery/meson.build
index 52993c32dbb..0b79896b61c 100644
--- a/src/test/recovery/meson.build
+++ b/src/test/recovery/meson.build
@@ -56,7 +56,7 @@ tests += {
       't/045_archive_restartpoint.pl',
       't/046_checkpoint_logical_slot.pl',
       't/047_checkpoint_physical_slot.pl',
-      't/048_vacuum_horizon_floor.pl'
+      't/048_vacuum_horizon_floor.pl',
     ],
   },
 }
-- 
2.47.1

