1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Fix a race in 035_standby_logical_decoding.pl

Buildfarm animals francolin and kestrel reported intermittent failures
in 035_standby_logical_decoding.pl.

The test checks that replaying DROP DATABASE on a standby terminates
pg_recvlogical with the expected recovery-conflict message and removes
the database's replication slots. To exercise this while pg_recvlogical
is streaming, the test must wait for streaming to start before dropping
the database on the primary.

Previously, the test treated an active slot in pg_replication_slots as
confirmation that pg_recvlogical was streaming. However, the slot can
become active before pg_recvlogical has entered streaming mode. If
DROP DATABASE is replayed during this window, pg_recvlogical can report
a connection-closed error instead of the recovery-conflict message,
causing the test to fail.

Run pg_recvlogical with --verbose and wait for "streaming initiated"
instead of checking whether the slot is active. This ensures that
pg_recvlogical has entered streaming mode before the database is
dropped on the primary.

Back-patch to v16, where this test was introduced.

Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Alexander Lakhin <exclusion@gmail.com>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/a50ff89b-fb2c-4912-8f89-50dd0bd0916b@gmail.com
Backpatch-through: 16
This commit is contained in:
Fujii Masao
2026-10-22 09:23:18 +09:00
parent 391fded1e5
commit c1b3845ade

View File

@@ -69,12 +69,13 @@ sub drop_logical_slots
} }
# Acquire one of the standby logical slots created by create_logical_slots(). # Acquire one of the standby logical slots created by create_logical_slots().
# In case wait is true we are waiting for an active pid on the 'activeslot' slot. # If wait is true, wait for pg_recvlogical to enter streaming mode.
# If wait is not true it means we are testing a known failure scenario. # Otherwise, starting replication is expected to fail.
sub make_slot_active sub make_slot_active
{ {
my ($node, $slot_prefix, $wait, $to_stdout, $to_stderr) = @_; my ($node, $slot_prefix, $wait, $to_stdout, $to_stderr) = @_;
my $slot_user_handle; my $slot_user_handle;
my $timeout = IPC::Run::timeout($default_timeout);
my $active_slot = $slot_prefix . 'activeslot'; my $active_slot = $slot_prefix . 'activeslot';
$slot_user_handle = IPC::Run::start( $slot_user_handle = IPC::Run::start(
@@ -85,20 +86,20 @@ sub make_slot_active
'include-xids=0', '-o', 'include-xids=0', '-o',
'skip-empty-xacts=1', '--no-loop', 'skip-empty-xacts=1', '--no-loop',
'--start', '-f', '--start', '-f',
'-' '-', '--verbose'
], ],
'>', '>',
$to_stdout, $to_stdout,
'2>', '2>',
$to_stderr, $to_stderr,
IPC::Run::timeout($default_timeout)); $timeout);
if ($wait) if ($wait)
{ {
# make sure activeslot is in use # Make sure that pg_recvlogical has entered streaming mode.
$node->poll_query_until('testdb', pump_until($slot_user_handle, $timeout, $to_stderr,
qq[SELECT EXISTS (SELECT 1 FROM pg_replication_slots WHERE slot_name = '$active_slot' AND active_pid IS NOT NULL)] qr/streaming initiated/)
) or die "slot never became active"; or die "pg_recvlogical did not enter streaming mode";
} }
return $slot_user_handle; return $slot_user_handle;
} }