po 18. 11. 2019 v 7:39 odesílatel Pavel Stehule <pavel.steh...@gmail.com> napsal:
> > > po 18. 11. 2019 v 7:37 odesílatel Amit Kapila <amit.kapil...@gmail.com> > napsal: > >> On Mon, Nov 18, 2019 at 10:59 AM Pavel Stehule <pavel.steh...@gmail.com> >> wrote: >> > po 18. 11. 2019 v 6:24 odesílatel Amit Kapila <amit.kapil...@gmail.com> >> napsal: >> >> >> >> On Mon, Nov 18, 2019 at 10:33 AM Pavel Stehule < >> pavel.steh...@gmail.com> wrote: >> >> > >> >> > po 18. 11. 2019 v 4:43 odesílatel vignesh C <vignes...@gmail.com> >> napsal: >> >> >> >> >> >> >> >> >> I had seen that isolation test(src/test/isolation) has a framework >> to >> >> >> support this. You can have a look to see if it can be handled using >> >> >> that. >> >> > >> >> > >> >> > I'll look there >> >> > >> >> >> >> If we want to have a test for this, then you might want to look at >> >> test src/test/recovery/t/013_crash_restart. In that test, we keep a >> >> connection open and then validate whether it is terminated. Having >> >> said that, I think it might be better to add this as a separate test >> >> patch apart from main patch because it is a bit of a timing-dependent >> >> test and might fail on some slow machines. We can always revert this >> >> if it turns out to be an unstable test. >> > >> > >> > +1 >> > >> >> So, are you planning to give it a try? I think even if we want to >> commit this separately, it is better to have a test for this before we >> commit. >> > > I'll send this test today > here is it Regards Pavel > > Pavel > > >> >> -- >> With Regards, >> Amit Kapila. >> EnterpriseDB: http://www.enterprisedb.com >> >
diff --git a/src/bin/scripts/t/060_dropdb_force.pl b/src/bin/scripts/t/060_dropdb_force.pl new file mode 100644 index 0000000000..b895a7fbba --- /dev/null +++ b/src/bin/scripts/t/060_dropdb_force.pl @@ -0,0 +1,149 @@ +# +# Tests killing session connected to dropped database +# +use strict; +use warnings; +use PostgresNode; +use TestLib; +use Test::More tests => 10; + +# To avoid hanging while expecting some specific input from a psql +# instance being driven by us, add a timeout high enough that it +# should never trigger even on very slow machines, unless something +# is really wrong. +my $psql_timeout = IPC::Run::timer(60); + +my $node = get_new_node('master'); +$node->init; +$node->start; + +# Create database that will be dropped +$node->safe_psql('postgres', 'CREATE DATABASE foobar1'); + +# Run psql, keeping session alive, so we have an alive backend to kill. +my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', ''); +my $killme = IPC::Run::start( + [ + 'psql', '-X', '-qAt', '-v', 'ON_ERROR_STOP=1', '-f', '-', '-d', + $node->connstr('foobar1') + ], + '<', + \$killme_stdin, + '>', + \$killme_stdout, + '2>', + \$killme_stderr, + $psql_timeout); + +#Ensure killme process is active +$killme_stdin .= q[ +SELECT pg_backend_pid(); +]; +ok(pump_until($killme, \$killme_stdout, qr/[[:digit:]]+[\r\n]$/m), + 'acquired pid'); +my $pid = $killme_stdout; +chomp($pid); +$killme_stdout = ''; +$killme_stderr = ''; + +# and it is connected to foobar1 database +is($node->safe_psql('postgres', qq[SELECT pid FROM pg_stat_activity WHERE datname='foobar1' AND pid = $pid;]), + $pid, 'database foobar1 is used'); + +$node->safe_psql('postgres', 'DROP DATABASE foobar1 WITH (FORCE)'); + +# Check that psql sees the killed backend as having been terminated +$killme_stdin .= q[ +SELECT 1; +]; +ok( pump_until( + $killme, + \$killme_stderr, + qr/FATAL: terminating connection due to administrator command/m + ), + "psql query died successfully after SIGTERM"); +$killme_stderr = ''; +$killme_stdout = ''; +$killme->finish; + +# and there is not a database with this name +is($node->safe_psql('postgres', qq[SELECT EXISTS(SELECT * FROM pg_database WHERE datname='foobar1');]), + 'f', 'database foobar1 was removed'); + +# Create database that will be dropped +$node->safe_psql('postgres', 'CREATE DATABASE foobar1'); + +# restart psql processes, now that the crash cycle finished +($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', ''); +$killme->run(); + +# Acquire pid of new backend +$killme_stdin .= q[ +SELECT pg_backend_pid(); +]; +ok(pump_until($killme, \$killme_stdout, qr/[[:digit:]]+[\r\n]$/m), + "acquired pid for SIGKILL"); +$pid = $killme_stdout; +chomp($pid); +$killme_stdout = ''; +$killme_stderr = ''; + +# and it is connected to foobar1 database +is($node->safe_psql('postgres', qq[SELECT pid FROM pg_stat_activity WHERE datname='foobar1' AND pid = $pid;]), + $pid, 'database foobar1 is used'); + +# Now drop database with dropdb --force command +$node->issues_sql_like( + [ 'dropdb', '--force', 'foobar1' ], + qr/statement: DROP DATABASE foobar1 WITH \(FORCE\);/, + 'SQL DROP DATABASE (FORCE) run'); + +# Check that psql sees the killed backend as having been terminated +$killme_stdin .= q[ +SELECT 1; +]; +ok( pump_until( + $killme, + \$killme_stderr, + qr/FATAL: terminating connection due to administrator command/m + ), + "psql query died successfully after SIGTERM"); +$killme_stderr = ''; +$killme_stdout = ''; +$killme->finish; + +# and there is not a database with this name +is($node->safe_psql('postgres', qq[SELECT EXISTS(SELECT * FROM pg_database WHERE datname='foobar1');]), + 'f', 'database foobar1 was removed'); + +$node->stop(); + +# Pump until string is matched, or timeout occurs +sub pump_until +{ + my ($proc, $stream, $untl) = @_; + $proc->pump_nb(); + while (1) + { + last if $$stream =~ /$untl/; + if ($psql_timeout->is_expired) + { + diag("aborting wait: program timed out"); + diag("stream contents: >>", $$stream, "<<"); + diag("pattern searched for: ", $untl); + + return 0; + } + if (not $proc->pumpable()) + { + diag("aborting wait: program died"); + diag("stream contents: >>", $$stream, "<<"); + diag("pattern searched for: ", $untl); + + return 0; + } + $proc->pump(); + } + return 1; + +}