Skip to content

Commit 1f2e51e

Browse files
committed
Fix assertion failure with replication slot release in single-user mode
Some replication slot manipulations (logical decoding via SQL, advancing) were failing an assertion when releasing a slot in single-user mode, because active_pid was not set in a ReplicationSlot when its slot is acquired. ReplicationSlotAcquire() has some logic to be able to work with the single-user mode. This commit sets ReplicationSlot->active_pid to MyProcPid, to let the slot-related logic fall-through, considering the single process as the one holding the slot. Some TAP tests are added for various replication slot functions with the single-user mode, while on it, for slot creation, drop, advancing, copy and logical decoding with multiple slot types (temporary, physical vs logical). These tests are skipped on Windows, as direct calls of postgres --single would fail on permission failures. There is no platform-specific behavior that needs to be checked, so living with this restriction should be fine. The CI is OK with that, now let's see what the buildfarm tells. Author: Hayato Kuroda <kuroda.hayato@fujitsu.com> Reviewed-by: Paul A. Jungwirth <pj@illuminatedcomputing.com> Reviewed-by: Mutaamba Maasha <maasha@gmail.com> Discussion: https://postgr.es/m/OSCPR01MB14966ED588A0328DAEBE8CB25F5FA2@OSCPR01MB14966.jpnprd01.prod.outlook.com Backpatch-through: 13
1 parent 6429e5b commit 1f2e51e

File tree

4 files changed

+99
-2
lines changed

4 files changed

+99
-2
lines changed

src/backend/replication/slot.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ ReplicationSlotAcquire(const char *name, bool nowait, bool error_if_invalid)
653653
}
654654
else
655655
{
656-
active_pid = MyProcPid;
656+
s->active_pid = active_pid = MyProcPid;
657657
ReplicationSlotSetInactiveSince(s, 0, true);
658658
}
659659
LWLockRelease(ReplicationSlotControlLock);

src/test/modules/test_misc/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
TAP_TESTS = 1
44

5-
EXTRA_INSTALL=src/test/modules/injection_points
5+
EXTRA_INSTALL=src/test/modules/injection_points \
6+
contrib/test_decoding
67

78
export enable_injection_points
89

src/test/modules/test_misc/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ tests += {
1616
't/005_timeouts.pl',
1717
't/006_signal_autovacuum.pl',
1818
't/007_catcache_inval.pl',
19+
't/008_replslot_single_user.pl',
1920
],
2021
},
2122
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Copyright (c) 2025, PostgreSQL Global Development Group
2+
3+
# Test manipulations of replication slots with the single-user mode.
4+
5+
use strict;
6+
use warnings;
7+
use PostgreSQL::Test::Cluster;
8+
use PostgreSQL::Test::Utils;
9+
use Test::More;
10+
11+
# Skip the tests on Windows, as single-user mode would fail on permission
12+
# failure with privileged accounts.
13+
if ($windows_os)
14+
{
15+
plan skip_all => 'this test is not supported by this platform';
16+
}
17+
18+
# Run set of queries in single-user mode.
19+
sub test_single_mode
20+
{
21+
my ($node, $queries, $testname) = @_;
22+
23+
my $result = run_log(
24+
[
25+
'postgres', '--single', '-F',
26+
'-c' => 'exit_on_error=true',
27+
'-D' => $node->data_dir,
28+
'postgres'
29+
],
30+
'<' => \$queries);
31+
32+
ok($result, $testname);
33+
}
34+
35+
my $slot_logical = 'slot_logical';
36+
my $slot_physical = 'slot_physical';
37+
38+
# Initialize a node
39+
my $node = PostgreSQL::Test::Cluster->new('node');
40+
$node->init(allows_streaming => "logical");
41+
$node->start;
42+
43+
# Define initial table
44+
$node->safe_psql('postgres', "CREATE TABLE foo (id int)");
45+
46+
$node->stop;
47+
48+
test_single_mode(
49+
$node,
50+
"SELECT pg_create_logical_replication_slot('$slot_logical', 'test_decoding')",
51+
"logical slot creation");
52+
test_single_mode(
53+
$node,
54+
"SELECT pg_create_physical_replication_slot('$slot_physical', true)",
55+
"physical slot creation");
56+
test_single_mode(
57+
$node,
58+
"SELECT pg_create_physical_replication_slot('slot_tmp', true, true)",
59+
"temporary physical slot creation");
60+
61+
test_single_mode(
62+
$node, qq(
63+
INSERT INTO foo VALUES (1);
64+
SELECT pg_logical_slot_get_changes('$slot_logical', NULL, NULL);
65+
),
66+
"logical decoding");
67+
68+
test_single_mode(
69+
$node,
70+
"SELECT pg_replication_slot_advance('$slot_logical', pg_current_wal_lsn())",
71+
"logical slot advance");
72+
test_single_mode(
73+
$node,
74+
"SELECT pg_replication_slot_advance('$slot_physical', pg_current_wal_lsn())",
75+
"physical slot advance");
76+
77+
test_single_mode(
78+
$node,
79+
"SELECT pg_copy_logical_replication_slot('$slot_logical', 'slot_log_copy')",
80+
"logical slot copy");
81+
test_single_mode(
82+
$node,
83+
"SELECT pg_copy_physical_replication_slot('$slot_physical', 'slot_phy_copy')",
84+
"physical slot copy");
85+
86+
test_single_mode(
87+
$node,
88+
"SELECT pg_drop_replication_slot('$slot_logical')",
89+
"logical slot drop");
90+
test_single_mode(
91+
$node,
92+
"SELECT pg_drop_replication_slot('$slot_physical')",
93+
"physical slot drop");
94+
95+
done_testing();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy