summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut2021-08-25 09:54:58 +0000
committerPeter Eisentraut2021-08-25 10:02:08 +0000
commit43d4dd87977d5ed66961605649d61973caf80f40 (patch)
tree27822bf86b9d7ac1f2a3e1f155d05e3c7c269226
parentbb9ff46bc4e659a865deaeb1b9aeac8d1ff4d36f (diff)
psql: Make cancel test more timing robust
The previous coding relied on the PID file appearing and the query starting "fast enough", which can fail on slow machines. Also, there might have been an undocumented interference between alarm and IPC::Run. This new coding doesn't rely on any of these concurrency mechanisms. Instead, we wait unitl the PID file is complete before proceeding, and then also wait until the sleep query is registered by the server. Discussion: https://www.postgresql.org/message-id/flat/E1mH14Q-0002gh-HS%40gemulon.postgresql.org
-rw-r--r--src/bin/psql/t/020_cancel.pl35
1 files changed, 27 insertions, 8 deletions
diff --git a/src/bin/psql/t/020_cancel.pl b/src/bin/psql/t/020_cancel.pl
index 7713fff8e4..b3edaaf35d 100644
--- a/src/bin/psql/t/020_cancel.pl
+++ b/src/bin/psql/t/020_cancel.pl
@@ -7,6 +7,7 @@ use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 2;
+use Time::HiRes qw(usleep);
my $tempdir = TestLib::tempdir;
@@ -28,19 +29,37 @@ SKIP: {
my ($stdin, $stdout, $stderr);
# Test whether shell supports $PPID. It's part of POSIX, but some
- # pre-/non-POSIX shells don't support it (e.g., NetBSD, Solaris).
+ # pre-/non-POSIX shells don't support it (e.g., NetBSD).
$stdin = "\\! echo \$PPID";
IPC::Run::run(['psql', '-X', '-v', 'ON_ERROR_STOP=1'], '<', \$stdin, '>', \$stdout, '2>', \$stderr);
$stdout =~ /^\d+$/ or skip "shell apparently does not support \$PPID", 2;
- local $SIG{ALRM} = sub {
- my $psql_pid = TestLib::slurp_file("$tempdir/psql.pid");
- kill 'INT', $psql_pid;
- };
- alarm 1;
+ # Now start the real test
+ my $h = IPC::Run::start(['psql', '-X', '-v', 'ON_ERROR_STOP=1'], \$stdin, \$stdout, \$stderr);
- $stdin = "\\! echo \$PPID >$tempdir/psql.pid\nselect pg_sleep(3);";
- my $result = IPC::Run::run(['psql', '-X', '-v', 'ON_ERROR_STOP=1'], '<', \$stdin, '>', \$stdout, '2>', \$stderr);
+ # Get the PID
+ $stdout = '';
+ $stderr = '';
+ $stdin = "\\! echo \$PPID >$tempdir/psql.pid\n";
+ pump $h while length $stdin;
+ my $count;
+ my $psql_pid;
+ until (-s "$tempdir/psql.pid" and ($psql_pid = TestLib::slurp_file("$tempdir/psql.pid")) =~ /^\d+\n/s)
+ {
+ ($count++ < 180 * 100) or die "pid file did not appear";
+ usleep(10_000)
+ }
+
+ # Send sleep command and wait until the server has registered it
+ $stdin = "select pg_sleep(180);\n";
+ pump $h while length $stdin;
+ $node->poll_query_until('postgres', q{SELECT (SELECT count(*) FROM pg_stat_activity WHERE query ~ 'pg_sleep') > 0;})
+ or die "timed out";
+
+ # Send cancel request
+ kill 'INT', $psql_pid;
+
+ my $result = finish $h;
ok(!$result, 'query failed as expected');
like($stderr, qr/canceling statement due to user request/, 'query was canceled');