Fix walsender error cleanup code
In commit 850196b610
I (Álvaro) failed to handle the case of walsender
shutting down on an error before setting up its 'xlogreader' pointer;
the error handling code dereferences the pointer, causing a crash.
Fix by testing the pointer before trying to dereference it.
Kyotaro authored the code fix; I adopted Nathan's test case to be used
by the TAP tests and added the necessary PostgresNode change.
Reported-by: Nathan Bossart <bossartn@amazon.com>
Author: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Author: Álvaro Herrera <alvherre@alvh.no-ip.org>
Discussion: https://postgr.es/m/C04FC24E-903D-4423-B312-6910E4D846E5@amazon.com
This commit is contained in:
parent
14a9101091
commit
1d3743023e
|
@ -315,7 +315,7 @@ WalSndErrorCleanup(void)
|
||||||
ConditionVariableCancelSleep();
|
ConditionVariableCancelSleep();
|
||||||
pgstat_report_wait_end();
|
pgstat_report_wait_end();
|
||||||
|
|
||||||
if (xlogreader->seg.ws_file >= 0)
|
if (xlogreader != NULL && xlogreader->seg.ws_file >= 0)
|
||||||
wal_segment_close(xlogreader);
|
wal_segment_close(xlogreader);
|
||||||
|
|
||||||
if (MyReplicationSlot != NULL)
|
if (MyReplicationSlot != NULL)
|
||||||
|
|
|
@ -1386,6 +1386,12 @@ the B<timed_out> parameter is also given.
|
||||||
If B<timeout> is set and this parameter is given, the scalar it references
|
If B<timeout> is set and this parameter is given, the scalar it references
|
||||||
is set to true if the psql call times out.
|
is set to true if the psql call times out.
|
||||||
|
|
||||||
|
=item replication => B<value>
|
||||||
|
|
||||||
|
If set, add B<replication=value> to the conninfo string.
|
||||||
|
Passing the literal value C<database> results in a logical replication
|
||||||
|
connection.
|
||||||
|
|
||||||
=item extra_params => ['--single-transaction']
|
=item extra_params => ['--single-transaction']
|
||||||
|
|
||||||
If given, it must be an array reference containing additional parameters to B<psql>.
|
If given, it must be an array reference containing additional parameters to B<psql>.
|
||||||
|
@ -1414,10 +1420,17 @@ sub psql
|
||||||
|
|
||||||
my $stdout = $params{stdout};
|
my $stdout = $params{stdout};
|
||||||
my $stderr = $params{stderr};
|
my $stderr = $params{stderr};
|
||||||
|
my $replication = $params{replication};
|
||||||
my $timeout = undef;
|
my $timeout = undef;
|
||||||
my $timeout_exception = 'psql timed out';
|
my $timeout_exception = 'psql timed out';
|
||||||
my @psql_params =
|
my @psql_params = (
|
||||||
('psql', '-XAtq', '-d', $self->connstr($dbname), '-f', '-');
|
'psql',
|
||||||
|
'-XAtq',
|
||||||
|
'-d',
|
||||||
|
$self->connstr($dbname)
|
||||||
|
. (defined $replication ? " replication=$replication" : ""),
|
||||||
|
'-f',
|
||||||
|
'-');
|
||||||
|
|
||||||
# If the caller wants an array and hasn't passed stdout/stderr
|
# If the caller wants an array and hasn't passed stdout/stderr
|
||||||
# references, allocate temporary ones to capture them so we
|
# references, allocate temporary ones to capture them so we
|
||||||
|
|
|
@ -7,7 +7,7 @@ use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use PostgresNode;
|
use PostgresNode;
|
||||||
use TestLib;
|
use TestLib;
|
||||||
use Test::More tests => 12;
|
use Test::More tests => 13;
|
||||||
use Config;
|
use Config;
|
||||||
|
|
||||||
# Initialize master node
|
# Initialize master node
|
||||||
|
@ -27,12 +27,21 @@ $node_master->safe_psql('postgres',
|
||||||
qq[SELECT pg_create_logical_replication_slot('test_slot', 'test_decoding');]
|
qq[SELECT pg_create_logical_replication_slot('test_slot', 'test_decoding');]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# Cover walsender error shutdown code
|
||||||
|
my ($result, $stdout, $stderr) = $node_master->psql(
|
||||||
|
'template1',
|
||||||
|
qq[START_REPLICATION SLOT test_slot LOGICAL 0/0],
|
||||||
|
replication => 'database');
|
||||||
|
ok( $stderr =~
|
||||||
|
m/replication slot "test_slot" was not created in this database/,
|
||||||
|
"Logical decoding correctly fails to start");
|
||||||
|
|
||||||
$node_master->safe_psql('postgres',
|
$node_master->safe_psql('postgres',
|
||||||
qq[INSERT INTO decoding_test(x,y) SELECT s, s::text FROM generate_series(1,10) s;]
|
qq[INSERT INTO decoding_test(x,y) SELECT s, s::text FROM generate_series(1,10) s;]
|
||||||
);
|
);
|
||||||
|
|
||||||
# Basic decoding works
|
# Basic decoding works
|
||||||
my ($result) = $node_master->safe_psql('postgres',
|
$result = $node_master->safe_psql('postgres',
|
||||||
qq[SELECT pg_logical_slot_get_changes('test_slot', NULL, NULL);]);
|
qq[SELECT pg_logical_slot_get_changes('test_slot', NULL, NULL);]);
|
||||||
is(scalar(my @foobar = split /^/m, $result),
|
is(scalar(my @foobar = split /^/m, $result),
|
||||||
12, 'Decoding produced 12 rows inc BEGIN/COMMIT');
|
12, 'Decoding produced 12 rows inc BEGIN/COMMIT');
|
||||||
|
|
Loading…
Reference in New Issue