mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Fix TAP test for remove_temp_files_after_crash
The test included in cd91de0d17
had two simple flaws.
Firstly, the number of rows was low and on some platforms (e.g. 32-bit)
the sort did not require on-disk sort, so on those machines it was not
testing the automatic removal. The test was however failing, because
without any temporary files the base/pgsql_tmp directory was not even
created. Fixed by increasing the rowcount to 5000, which should be high
engough on any platform.
Secondly, the test used a simple sleep to wait for the temporary file to
be created. This is obviously problematic, because on slow machines (or
with valgrind, CLOBBER_CACHE_ALWAYS etc.) it may take a while to create
the temporary file. But we also want the tests run reasonably fast.
Fixed by instead relying on a UNIQUE constraint, blocking the query that
created the temporary file.
Author: Euler Taveira
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAH503wDKdYzyq7U-QJqGn%3DGm6XmoK%2B6_6xTJ-Yn5WSvoHLY1Ww%40mail.gmail.com
This commit is contained in:
@ -5,7 +5,6 @@ use PostgresNode;
|
|||||||
use TestLib;
|
use TestLib;
|
||||||
use Test::More;
|
use Test::More;
|
||||||
use Config;
|
use Config;
|
||||||
use Time::HiRes qw(usleep);
|
|
||||||
|
|
||||||
plan tests => 9;
|
plan tests => 9;
|
||||||
|
|
||||||
@ -33,8 +32,7 @@ $node->safe_psql(
|
|||||||
# create table, insert rows
|
# create table, insert rows
|
||||||
$node->safe_psql(
|
$node->safe_psql(
|
||||||
'postgres',
|
'postgres',
|
||||||
q[CREATE TABLE tab_crash (a text);
|
q[CREATE TABLE tab_crash (a integer UNIQUE);]);
|
||||||
INSERT INTO tab_crash (a) SELECT gen_random_uuid() FROM generate_series(1, 500);]);
|
|
||||||
|
|
||||||
# Run psql, keeping session alive, so we have an alive backend to kill.
|
# Run psql, keeping session alive, so we have an alive backend to kill.
|
||||||
my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', '');
|
my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', '');
|
||||||
@ -62,6 +60,32 @@ chomp($pid);
|
|||||||
$killme_stdout = '';
|
$killme_stdout = '';
|
||||||
$killme_stderr = '';
|
$killme_stderr = '';
|
||||||
|
|
||||||
|
# Open a 2nd session that will block the 1st one, using the UNIQUE constraint.
|
||||||
|
# This will prevent removal of the temporary file created by the 1st session.
|
||||||
|
my ($killme_stdin2, $killme_stdout2, $killme_stderr2) = ('', '', '');
|
||||||
|
my $killme2 = IPC::Run::start(
|
||||||
|
[
|
||||||
|
'psql', '-X', '-qAt', '-v', 'ON_ERROR_STOP=1', '-f', '-', '-d',
|
||||||
|
$node->connstr('postgres')
|
||||||
|
],
|
||||||
|
'<',
|
||||||
|
\$killme_stdin2,
|
||||||
|
'>',
|
||||||
|
\$killme_stdout2,
|
||||||
|
'2>',
|
||||||
|
\$killme_stderr2,
|
||||||
|
$psql_timeout);
|
||||||
|
|
||||||
|
# Insert one tuple and leave the transaction open
|
||||||
|
$killme_stdin2 .= q[
|
||||||
|
BEGIN;
|
||||||
|
SELECT $$insert-tuple-to-lock-next-insert$$;
|
||||||
|
INSERT INTO tab_crash (a) VALUES(1);
|
||||||
|
];
|
||||||
|
pump_until($killme2, \$killme_stdout2, qr/insert-tuple-to-lock-next-insert/m);
|
||||||
|
$killme_stdout2 = '';
|
||||||
|
$killme_stderr2 = '';
|
||||||
|
|
||||||
# Run the query that generates a temporary file and that will be killed before
|
# Run the query that generates a temporary file and that will be killed before
|
||||||
# it finishes. Since the query that generates the temporary file does not
|
# it finishes. Since the query that generates the temporary file does not
|
||||||
# return before the connection is killed, use a SELECT before to trigger
|
# return before the connection is killed, use a SELECT before to trigger
|
||||||
@ -69,22 +93,20 @@ $killme_stderr = '';
|
|||||||
$killme_stdin .= q[
|
$killme_stdin .= q[
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SELECT $$in-progress-before-sigkill$$;
|
SELECT $$in-progress-before-sigkill$$;
|
||||||
WITH foo AS (SELECT a FROM tab_crash ORDER BY a) SELECT a, pg_sleep(1) FROM foo;
|
INSERT INTO tab_crash (a) SELECT i FROM generate_series(1, 5000) s(i);
|
||||||
];
|
];
|
||||||
ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
|
ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
|
||||||
'select in-progress-before-sigkill');
|
'insert in-progress-before-sigkill');
|
||||||
$killme_stdout = '';
|
$killme_stdout = '';
|
||||||
$killme_stderr = '';
|
$killme_stderr = '';
|
||||||
|
|
||||||
# Wait some time so the temporary file is generated by SELECT
|
|
||||||
usleep(10_000);
|
|
||||||
|
|
||||||
# Kill with SIGKILL
|
# Kill with SIGKILL
|
||||||
my $ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
|
my $ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
|
||||||
is($ret, 0, 'killed process with KILL');
|
is($ret, 0, 'killed process with KILL');
|
||||||
|
|
||||||
# Close psql session
|
# Close psql session
|
||||||
$killme->finish;
|
$killme->finish;
|
||||||
|
$killme2->finish;
|
||||||
|
|
||||||
# Wait till server restarts
|
# Wait till server restarts
|
||||||
$node->poll_query_until('postgres', 'SELECT 1', '1');
|
$node->poll_query_until('postgres', 'SELECT 1', '1');
|
||||||
@ -118,6 +140,20 @@ chomp($pid);
|
|||||||
$killme_stdout = '';
|
$killme_stdout = '';
|
||||||
$killme_stderr = '';
|
$killme_stderr = '';
|
||||||
|
|
||||||
|
# Restart the 2nd psql session
|
||||||
|
($killme_stdin2, $killme_stdout2, $killme_stderr2) = ('', '', '');
|
||||||
|
$killme2->run();
|
||||||
|
|
||||||
|
# Insert one tuple and leave the transaction open
|
||||||
|
$killme_stdin2 .= q[
|
||||||
|
BEGIN;
|
||||||
|
SELECT $$insert-tuple-to-lock-next-insert$$;
|
||||||
|
INSERT INTO tab_crash (a) VALUES(1);
|
||||||
|
];
|
||||||
|
pump_until($killme2, \$killme_stdout2, qr/insert-tuple-to-lock-next-insert/m);
|
||||||
|
$killme_stdout2 = '';
|
||||||
|
$killme_stderr2 = '';
|
||||||
|
|
||||||
# Run the query that generates a temporary file and that will be killed before
|
# Run the query that generates a temporary file and that will be killed before
|
||||||
# it finishes. Since the query that generates the temporary file does not
|
# it finishes. Since the query that generates the temporary file does not
|
||||||
# return before the connection is killed, use a SELECT before to trigger
|
# return before the connection is killed, use a SELECT before to trigger
|
||||||
@ -125,22 +161,20 @@ $killme_stderr = '';
|
|||||||
$killme_stdin .= q[
|
$killme_stdin .= q[
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SELECT $$in-progress-before-sigkill$$;
|
SELECT $$in-progress-before-sigkill$$;
|
||||||
WITH foo AS (SELECT a FROM tab_crash ORDER BY a) SELECT a, pg_sleep(1) FROM foo;
|
INSERT INTO tab_crash (a) SELECT i FROM generate_series(1, 5000) s(i);
|
||||||
];
|
];
|
||||||
ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
|
ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
|
||||||
'select in-progress-before-sigkill');
|
'insert in-progress-before-sigkill');
|
||||||
$killme_stdout = '';
|
$killme_stdout = '';
|
||||||
$killme_stderr = '';
|
$killme_stderr = '';
|
||||||
|
|
||||||
# Wait some time so the temporary file is generated by SELECT
|
|
||||||
usleep(10_000);
|
|
||||||
|
|
||||||
# Kill with SIGKILL
|
# Kill with SIGKILL
|
||||||
$ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
|
$ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
|
||||||
is($ret, 0, 'killed process with KILL');
|
is($ret, 0, 'killed process with KILL');
|
||||||
|
|
||||||
# Close psql session
|
# Close psql session
|
||||||
$killme->finish;
|
$killme->finish;
|
||||||
|
$killme2->finish;
|
||||||
|
|
||||||
# Wait till server restarts
|
# Wait till server restarts
|
||||||
$node->poll_query_until('postgres', 'SELECT 1', '1');
|
$node->poll_query_until('postgres', 'SELECT 1', '1');
|
||||||
|
Reference in New Issue
Block a user