From d30416a303cf78639f71a3d192aa14116da28d4e Mon Sep 17 00:00:00 2001 From: Hayato Kuroda 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