}
else
{
- plan tests => 12;
+ plan tests => 18;
}
# 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 in a normal run, but low enough to actually see
# failures in a realistic amount of time.
-my $psql_timeout = 180;
+my $psql_timeout = IPC::Run::timer(10);
my $node = get_new_node('master');
$node->init(allows_streaming => 1);
\$killme_stdout,
'2>',
\$killme_stderr,
- IPC::Run::timeout($psql_timeout));
+ $psql_timeout);
# Need a second psql to check if crash-restart happened.
my ($monitor_stdin, $monitor_stdout, $monitor_stderr) = ('', '', '');
\$monitor_stdout,
'2>',
\$monitor_stderr,
- IPC::Run::timeout($psql_timeout));
+ $psql_timeout);
#create table, insert row that should survive
$killme_stdin .= q[
INSERT INTO alive VALUES($$committed-before-sigquit$$);
SELECT pg_backend_pid();
];
-$killme->pump until $killme_stdout =~ /[[:digit:]]+[\r\n]$/;
+ok(pump_until($killme, \$killme_stdout, qr/[[:digit:]]+[\r\n]$/m),
+ 'acquired pid for SIGQUIT');
my $pid = $killme_stdout;
chomp($pid);
$killme_stdout = '';
+$killme_stderr = '';
#insert a row that should *not* survive, due to in-progress xact
$killme_stdin .= q[
BEGIN;
INSERT INTO alive VALUES($$in-progress-before-sigquit$$) RETURNING status;
];
-$killme->pump until $killme_stdout =~ /in-progress-before-sigquit/;
+ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigquit/m),
+ 'inserted in-progress-before-sigquit');
$killme_stdout = '';
+$killme_stderr = '';
# Start longrunning query in second session, it's failure will signal
SELECT $$psql-connected$$;
SELECT pg_sleep(3600);
];
-$monitor->pump until $monitor_stdout =~ /psql-connected/;
-
+ok(pump_until($monitor, \$monitor_stdout, qr/psql-connected/m),
+ 'monitor connected');
+$monitor_stdout = '';
+$monitor_stderr = '';
# kill once with QUIT - we expect psql to exit, while emitting error message first
my $cnt = kill 'QUIT', $pid;
# Exactly process should have been alive to be killed
is($cnt, 1, "exactly one process killed with SIGQUIT");
-# Check that psql sees the killed backend as having been terminated
+# Check that psql sees the killed backend as having been terminated
$killme_stdin .= q[
SELECT 1;
];
-$killme->pump until $killme_stderr =~ /WARNING: terminating connection because of crash of another server process/;
-
-ok(1, "psql query died successfully after SIGQUIT");
+ok(pump_until($killme, \$killme_stderr, qr/WARNING: terminating connection because of crash of another server process/m),
+ "psql query died successfully after SIGQUIT");
+$killme_stderr = '';
+$killme_stdout = '';
$killme->kill_kill;
-# Check if the crash-restart cycle has occurred
-$monitor->pump until $monitor_stderr =~ /WARNING: terminating connection because of crash of another server process/;
+# Wait till server restarts - we should get the WARNING here, but
+# sometimes the server is unable to send that, if interrupted while
+# sending.
+ok(pump_until($monitor, \$monitor_stderr, qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m),
+ "psql monitor died successfully after SIGQUIT");
$monitor->kill_kill;
-ok(1, "psql monitor died successfully after SIGQUIT");
# Wait till server restarts
-is($node->poll_query_until('postgres', 'SELECT $$restarted$$;', 'restarted'), "1", "reconnected after SIGQUIT");
+is($node->poll_query_until('postgres', 'SELECT $$restarted after sigquit$$;', 'restarted after sigquit'),
+ "1", "reconnected after SIGQUIT");
+
# restart psql processes, now that the crash cycle finished
($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', '');
$killme_stdin .= q[
SELECT pg_backend_pid();
];
-$killme->pump until $killme_stdout =~ /[[:digit:]]+[\r\n]$/;
+ok(pump_until($killme, \$killme_stdout, qr/[[:digit:]]+[\r\n]$/m),
+ "acquired pid for SIGKILL");
$pid = $killme_stdout;
chomp($pid);
$pid = $killme_stdout;
+$killme_stdout = '';
+$killme_stderr = '';
# Insert test rows
$killme_stdin .= q[
BEGIN;
INSERT INTO alive VALUES($$in-progress-before-sigkill$$) RETURNING status;
];
-$killme->pump until $killme_stdout =~ /in-progress-before-sigkill/;
+ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
+ 'inserted in-progress-before-sigkill');
$killme_stdout = '';
+$killme_stderr = '';
# Re-start longrunning query in second session, it's failure will
# signal that crash-restart has occurred. The initial wait for the
SELECT $$psql-connected$$;
SELECT pg_sleep(3600);
];
-$monitor->pump until $monitor_stdout =~ /psql-connected/;
+ok(pump_until($monitor, \$monitor_stdout, qr/psql-connected/m),
+ 'monitor connected');
$monitor_stdout = '';
+$monitor_stderr = '';
# kill with SIGKILL this time - we expect the backend to exit, without
$killme_stdin .= q[
SELECT 1;
];
-$killme->pump until $killme_stderr =~ /server closed the connection unexpectedly/;
+ok(pump_until($killme, \$killme_stderr, qr/server closed the connection unexpectedly/m),
+ "psql query died successfully after SIGKILL");
$killme->kill_kill;
-ok(1, "psql query died successfully after SIGKILL");
-# Wait till server restarts (note that we should get the WARNING here)
-$monitor->pump until $monitor_stderr =~ /WARNING: terminating connection because of crash of another server process/;
-ok(1, "psql monitor died successfully after SIGKILL");
+# Wait till server restarts - we should get the WARNING here, but
+# sometimes the server is unable to send that, if interrupted while
+# sending.
+ok(pump_until($monitor, \$monitor_stderr, qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m),
+ "psql monitor died successfully after SIGKILL");
$monitor->kill_kill;
# Wait till server restarts
'after-orderly-restart', 'can still write after orderly restart');
$node->stop();
+
+# Pump until string is matched, or timeout occurs
+sub pump_until
+{
+ my ($proc, $stream, $untl) = @_;
+ $proc->pump_nb();
+ while (1)
+ {
+ 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();
+ last if $$stream =~ /$untl/;
+ }
+ return 1;
+
+};