From 97b9ba4374b5423f40b3868d83b515d94969dfa6 Mon Sep 17 00:00:00 2001 From: Anthonin Bonnefoy Date: Tue, 17 Mar 2026 15:07:55 +0100 Subject: Add test shutting down walsender with unflushed record 6eedb2a5fd8 fixed an issue where the walsender was stuck in a busy loop, trying to read an unflused record. d927b4bd97 fixed another issue introduced by the previous commit, where XLogFlush would be called past the end of the generated WAL, generating an error log. This commit adds a test to cover those two fixes. By writing a logical message of a specific size, we can reach a state where the last record is crossing the page boundary, and ends at the end of the next page, recreating the conditions for the aforementioned issues. --- src/test/recovery/t/006_logical_decoding.pl | 50 ++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/test/recovery/t/006_logical_decoding.pl b/src/test/recovery/t/006_logical_decoding.pl index 97d11f98b59..1efb6f7b527 100644 --- a/src/test/recovery/t/006_logical_decoding.pl +++ b/src/test/recovery/t/006_logical_decoding.pl @@ -275,7 +275,55 @@ is( $node_primary->safe_psql( qq(Check that reset timestamp is later after resetting stats for slot '$stats_test_slot1' again.) ); -# done with the node +SKIP: +{ + + # some Windows Perls at least don't like IPC::Run's start/kill_kill regime. + skip "Test fails on Windows perl", 2 if $Config{osname} eq 'MSWin32'; + + # Test stopping the primary with an active walsender and an unflushed record + # which crosses the page boundary and ends at the end of the next page. + # + # First, start pg_recvlogical to have an active walsender + my $pg_recvlogical = IPC::Run::start( + [ + 'pg_recvlogical', + '--dbname' => $node_primary->connstr('postgres'), + '--slot' => 'test_slot', + '--file' => '-', + '--start' + ]); + + # Then, we write a logical message WAL record which finishes at the end of a + # WAL page, using a rollback so the WAL record isn't flushed. + # + # The size of a WAL logical message record is 55 bytes + message length + # Starting from a fresh WAL segment, we have: + # - 8152 bytes available in the first page (long header) + # - 8168 bytes available in the second page (short header) + # We need to write 16320 bytes of logical message WAL record, which can be done + # using a 16265 bytes long message. + $node_primary->safe_psql('postgres', + qq[ + SELECT pg_switch_wal(); + BEGIN; + SELECT pg_logical_emit_message(false, '', repeat('a', 16265), false); + ROLLBACK; + ] + ); + + # try to restart + $node_primary->restart; + $pg_recvlogical->kill_kill; + + my $logfile = slurp_file($node_primary->logfile()); + unlike( + $logfile, + qr/request to flush past end of generated WAL/, + "There's no flush request past end of generated WAL"); +} + +# stop the node $node_primary->stop; done_testing(); -- 2.53.0