mirror of https://github.com/postgres/postgres
This reverts commitspull/40/head2f932f71d9
,16ee6eaf80
and6f0e190056
. The buildfarm has revealed several bugs. Back-patch like the original commits. Discussion: https://postgr.es/m/20190404145319.GA1720877@rfd.leadboat.com
parent
794c543b17
commit
82150a05be
@ -1,177 +0,0 @@ |
|||||||
# |
|
||||||
# Tests of pg_shmem.h functions |
|
||||||
# |
|
||||||
use strict; |
|
||||||
use warnings; |
|
||||||
use IPC::Run 'run'; |
|
||||||
use PostgresNode; |
|
||||||
use Test::More; |
|
||||||
use TestLib; |
|
||||||
|
|
||||||
plan tests => 6; |
|
||||||
|
|
||||||
my $tempdir = TestLib::tempdir; |
|
||||||
my $port; |
|
||||||
|
|
||||||
# Log "ipcs" diffs on a best-effort basis, swallowing any error. |
|
||||||
my $ipcs_before = "$tempdir/ipcs_before"; |
|
||||||
eval { run_log [ 'ipcs', '-am' ], '>', $ipcs_before; }; |
|
||||||
|
|
||||||
sub log_ipcs |
|
||||||
{ |
|
||||||
eval { run_log [ 'ipcs', '-am' ], '|', [ 'diff', $ipcs_before, '-' ] }; |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
# With Unix sockets, choose a port number such that the port number's first |
|
||||||
# IpcMemoryKey candidate is available. If multiple copies of this test run |
|
||||||
# concurrently, they will pick different ports. In the absence of collisions |
|
||||||
# from other shmget() activity, gnat starts with key 0x7d001 (512001), and |
|
||||||
# flea starts with key 0x7d002 (512002). With TCP, the first get_new_node |
|
||||||
# picks a port number. |
|
||||||
my $port_holder; |
|
||||||
if (!$PostgresNode::use_tcp) |
|
||||||
{ |
|
||||||
for ($port = 512; $port < 612; ++$port) |
|
||||||
{ |
|
||||||
$port_holder = PostgresNode->get_new_node( |
|
||||||
"port${port}_holder", |
|
||||||
port => $port, |
|
||||||
own_host => 1); |
|
||||||
$port_holder->init; |
|
||||||
$port_holder->start; |
|
||||||
# Match the AddToDataDirLockFile() call in sysv_shmem.c. Assume all |
|
||||||
# systems not using sysv_shmem.c do use TCP. |
|
||||||
my $shmem_key_line_prefix = sprintf("%9lu ", 1 + $port * 1000); |
|
||||||
last |
|
||||||
if slurp_file($port_holder->data_dir . '/postmaster.pid') =~ |
|
||||||
/^$shmem_key_line_prefix/m; |
|
||||||
$port_holder->stop; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
# Node setup. |
|
||||||
sub init_start |
|
||||||
{ |
|
||||||
my $name = shift; |
|
||||||
my $ret = PostgresNode->get_new_node($name, port => $port, own_host => 1); |
|
||||||
defined($port) or $port = $ret->port; # same port for all nodes |
|
||||||
$ret->init; |
|
||||||
$ret->start; |
|
||||||
log_ipcs(); |
|
||||||
return $ret; |
|
||||||
} |
|
||||||
my $gnat = init_start 'gnat'; |
|
||||||
my $flea = init_start 'flea'; |
|
||||||
|
|
||||||
# Upon postmaster death, postmaster children exit automatically. |
|
||||||
$gnat->kill9; |
|
||||||
log_ipcs(); |
|
||||||
$flea->restart; # flea ignores the shm key gnat abandoned. |
|
||||||
log_ipcs(); |
|
||||||
poll_start($gnat); # gnat recycles its former shm key. |
|
||||||
log_ipcs(); |
|
||||||
|
|
||||||
# After clean shutdown, the nodes swap shm keys. |
|
||||||
$gnat->stop; |
|
||||||
$flea->restart; |
|
||||||
log_ipcs(); |
|
||||||
$gnat->start; |
|
||||||
log_ipcs(); |
|
||||||
|
|
||||||
# Scenarios involving no postmaster.pid, dead postmaster, and a live backend. |
|
||||||
# Use a regress.c function to emulate the responsiveness of a backend working |
|
||||||
# through a CPU-intensive task. |
|
||||||
$gnat->safe_psql('postgres', <<EOSQL); |
|
||||||
CREATE FUNCTION wait_pid(int) |
|
||||||
RETURNS void |
|
||||||
AS '$ENV{REGRESS_SHLIB}' |
|
||||||
LANGUAGE C STRICT; |
|
||||||
EOSQL |
|
||||||
my $slow_query = 'SELECT wait_pid(pg_backend_pid())'; |
|
||||||
my ($stdout, $stderr); |
|
||||||
my $slow_client = IPC::Run::start( |
|
||||||
[ |
|
||||||
'psql', '-X', '-qAt', '-d', $gnat->connstr('postgres'), |
|
||||||
'-c', $slow_query |
|
||||||
], |
|
||||||
'<', |
|
||||||
\undef, |
|
||||||
'>', |
|
||||||
\$stdout, |
|
||||||
'2>', |
|
||||||
\$stderr, |
|
||||||
IPC::Run::timeout(900)); # five times the poll_query_until timeout |
|
||||||
ok( $gnat->poll_query_until( |
|
||||||
'postgres', |
|
||||||
"SELECT 1 FROM pg_stat_activity WHERE query = '$slow_query'", '1'), |
|
||||||
'slow query started'); |
|
||||||
my $slow_pid = $gnat->safe_psql('postgres', |
|
||||||
"SELECT pid FROM pg_stat_activity WHERE query = '$slow_query'"); |
|
||||||
$gnat->kill9; |
|
||||||
unlink($gnat->data_dir . '/postmaster.pid'); |
|
||||||
$gnat->rotate_logfile; # on Windows, can't open old log for writing |
|
||||||
log_ipcs(); |
|
||||||
# Reject ordinary startup. |
|
||||||
ok(!$gnat->start(fail_ok => 1), 'live query blocks restart'); |
|
||||||
like( |
|
||||||
slurp_file($gnat->logfile), |
|
||||||
qr/pre-existing shared memory block/, |
|
||||||
'detected live backend via shared memory'); |
|
||||||
# Reject single-user startup. |
|
||||||
my $single_stderr; |
|
||||||
ok( !run_log( |
|
||||||
[ 'postgres', '--single', '-D', $gnat->data_dir, 'template1' ], |
|
||||||
'<', \('SELECT 1 + 1'), '2>', \$single_stderr), |
|
||||||
'live query blocks --single'); |
|
||||||
print STDERR $single_stderr; |
|
||||||
like( |
|
||||||
$single_stderr, |
|
||||||
qr/pre-existing shared memory block/, |
|
||||||
'single-user mode detected live backend via shared memory'); |
|
||||||
log_ipcs(); |
|
||||||
# Fail to reject startup if shm key N has become available and we crash while |
|
||||||
# using key N+1. This is unwanted, but expected. Windows is immune, because |
|
||||||
# its GetSharedMemName() use DataDir strings, not numeric keys. |
|
||||||
$flea->stop; # release first key |
|
||||||
is( $gnat->start(fail_ok => 1), |
|
||||||
$TestLib::windows_os ? 0 : 1, |
|
||||||
'key turnover fools only sysv_shmem.c'); |
|
||||||
$gnat->stop; # release first key (no-op on $TestLib::windows_os) |
|
||||||
$flea->start; # grab first key |
|
||||||
# cleanup |
|
||||||
TestLib::system_log('pg_ctl', 'kill', 'QUIT', $slow_pid); |
|
||||||
$slow_client->finish; # client has detected backend termination |
|
||||||
log_ipcs(); |
|
||||||
poll_start($gnat); # recycle second key |
|
||||||
|
|
||||||
$gnat->stop; |
|
||||||
$flea->stop; |
|
||||||
$port_holder->stop if $port_holder; |
|
||||||
log_ipcs(); |
|
||||||
|
|
||||||
|
|
||||||
# When postmaster children are slow to exit after postmaster death, we may |
|
||||||
# need retries to start a new postmaster. |
|
||||||
sub poll_start |
|
||||||
{ |
|
||||||
my ($node) = @_; |
|
||||||
|
|
||||||
my $max_attempts = 180 * 10; |
|
||||||
my $attempts = 0; |
|
||||||
|
|
||||||
while ($attempts < $max_attempts) |
|
||||||
{ |
|
||||||
$node->start(fail_ok => 1) && return 1; |
|
||||||
|
|
||||||
# Wait 0.1 second before retrying. |
|
||||||
usleep(100_000); |
|
||||||
|
|
||||||
$attempts++; |
|
||||||
} |
|
||||||
|
|
||||||
# No success within 180 seconds. Try one last time without fail_ok, which |
|
||||||
# will BAIL_OUT unless it succeeds. |
|
||||||
$node->start && return 1; |
|
||||||
return 0; |
|
||||||
} |
|
Loading…
Reference in new issue