From 740539c90d489ceef7ae47ac10272122e22da889 Mon Sep 17 00:00:00 2001 From: Hayato Kuroda Date: Thu, 25 Jun 2026 11:00:23 +0900 Subject: [PATCH v2] 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 Author: Hayato Kuroda Reviewed-by: Alexander Lakhin Reviewed-by: Bertrand Drouvot Discussion: https://postgr.es/m/a50ff89b-fb2c-4912-8f89-50dd0bd0916b@gmail.com Backpatch-through: 16 --- .../recovery/t/035_standby_logical_decoding.pl | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/test/recovery/t/035_standby_logical_decoding.pl b/src/test/recovery/t/035_standby_logical_decoding.pl index 9c5b1ba64a8..c9a75d231dc 100644 --- a/src/test/recovery/t/035_standby_logical_decoding.pl +++ b/src/test/recovery/t/035_standby_logical_decoding.pl @@ -69,12 +69,13 @@ sub drop_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 not true it means we are testing a known failure scenario. +# If wait is true, wait for pg_recvlogical to enter streaming mode. +# Otherwise, starting replication is expected to fail. sub make_slot_active { my ($node, $slot_prefix, $wait, $to_stdout, $to_stderr) = @_; my $slot_user_handle; + my $timeout = IPC::Run::timeout($default_timeout); my $active_slot = $slot_prefix . 'activeslot'; $slot_user_handle = IPC::Run::start( @@ -85,20 +86,20 @@ sub make_slot_active 'include-xids=0', '-o', 'skip-empty-xacts=1', '--no-loop', '--start', '-f', - '-' + '-', '--verbose' ], '>', $to_stdout, '2>', $to_stderr, - IPC::Run::timeout($default_timeout)); + $timeout); if ($wait) { - # make sure activeslot is in use - $node->poll_query_until('testdb', - qq[SELECT EXISTS (SELECT 1 FROM pg_replication_slots WHERE slot_name = '$active_slot' AND active_pid IS NOT NULL)] - ) or die "slot never became active"; + # Make sure that pg_recvlogical has entered streaming mode. + pump_until($slot_user_handle, $timeout, $to_stderr, + qr/streaming initiated/) + or die "pg_recvlogical did not enter streaming mode"; } return $slot_user_handle; } -- 2.56.0