Skip to content

Commit a16b2b9

Browse files
committed
Fix TAP test for remove_temp_files_after_crash
The test included in cd91de0 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
1 parent 5b2266e commit a16b2b9

File tree

1 file changed

+47
-13
lines changed

1 file changed

+47
-13
lines changed

src/test/recovery/t/022_crash_temp_files.pl

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use TestLib;
66
use Test::More;
77
use Config;
8-
use Time::HiRes qw(usleep);
98

109
plan tests => 9;
1110

@@ -33,8 +32,7 @@
3332
# create table, insert rows
3433
$node->safe_psql(
3534
'postgres',
36-
q[CREATE TABLE tab_crash (a text);
37-
INSERT INTO tab_crash (a) SELECT gen_random_uuid() FROM generate_series(1, 500);]);
35+
q[CREATE TABLE tab_crash (a integer UNIQUE);]);
3836

3937
# Run psql, keeping session alive, so we have an alive backend to kill.
4038
my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', '');
@@ -62,29 +60,53 @@
6260
$killme_stdout = '';
6361
$killme_stderr = '';
6462

63+
# Open a 2nd session that will block the 1st one, using the UNIQUE constraint.
64+
# This will prevent removal of the temporary file created by the 1st session.
65+
my ($killme_stdin2, $killme_stdout2, $killme_stderr2) = ('', '', '');
66+
my $killme2 = IPC::Run::start(
67+
[
68+
'psql', '-X', '-qAt', '-v', 'ON_ERROR_STOP=1', '-f', '-', '-d',
69+
$node->connstr('postgres')
70+
],
71+
'<',
72+
\$killme_stdin2,
73+
'>',
74+
\$killme_stdout2,
75+
'2>',
76+
\$killme_stderr2,
77+
$psql_timeout);
78+
79+
# Insert one tuple and leave the transaction open
80+
$killme_stdin2 .= q[
81+
BEGIN;
82+
SELECT $$insert-tuple-to-lock-next-insert$$;
83+
INSERT INTO tab_crash (a) VALUES(1);
84+
];
85+
pump_until($killme2, \$killme_stdout2, qr/insert-tuple-to-lock-next-insert/m);
86+
$killme_stdout2 = '';
87+
$killme_stderr2 = '';
88+
6589
# Run the query that generates a temporary file and that will be killed before
6690
# it finishes. Since the query that generates the temporary file does not
6791
# return before the connection is killed, use a SELECT before to trigger
6892
# pump_until.
6993
$killme_stdin .= q[
7094
BEGIN;
7195
SELECT $$in-progress-before-sigkill$$;
72-
WITH foo AS (SELECT a FROM tab_crash ORDER BY a) SELECT a, pg_sleep(1) FROM foo;
96+
INSERT INTO tab_crash (a) SELECT i FROM generate_series(1, 5000) s(i);
7397
];
7498
ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
75-
'select in-progress-before-sigkill');
99+
'insert in-progress-before-sigkill');
76100
$killme_stdout = '';
77101
$killme_stderr = '';
78102

79-
# Wait some time so the temporary file is generated by SELECT
80-
usleep(10_000);
81-
82103
# Kill with SIGKILL
83104
my $ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
84105
is($ret, 0, 'killed process with KILL');
85106

86107
# Close psql session
87108
$killme->finish;
109+
$killme2->finish;
88110

89111
# Wait till server restarts
90112
$node->poll_query_until('postgres', 'SELECT 1', '1');
@@ -118,29 +140,41 @@
118140
$killme_stdout = '';
119141
$killme_stderr = '';
120142

143+
# Restart the 2nd psql session
144+
($killme_stdin2, $killme_stdout2, $killme_stderr2) = ('', '', '');
145+
$killme2->run();
146+
147+
# Insert one tuple and leave the transaction open
148+
$killme_stdin2 .= q[
149+
BEGIN;
150+
SELECT $$insert-tuple-to-lock-next-insert$$;
151+
INSERT INTO tab_crash (a) VALUES(1);
152+
];
153+
pump_until($killme2, \$killme_stdout2, qr/insert-tuple-to-lock-next-insert/m);
154+
$killme_stdout2 = '';
155+
$killme_stderr2 = '';
156+
121157
# Run the query that generates a temporary file and that will be killed before
122158
# it finishes. Since the query that generates the temporary file does not
123159
# return before the connection is killed, use a SELECT before to trigger
124160
# pump_until.
125161
$killme_stdin .= q[
126162
BEGIN;
127163
SELECT $$in-progress-before-sigkill$$;
128-
WITH foo AS (SELECT a FROM tab_crash ORDER BY a) SELECT a, pg_sleep(1) FROM foo;
164+
INSERT INTO tab_crash (a) SELECT i FROM generate_series(1, 5000) s(i);
129165
];
130166
ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
131-
'select in-progress-before-sigkill');
167+
'insert in-progress-before-sigkill');
132168
$killme_stdout = '';
133169
$killme_stderr = '';
134170

135-
# Wait some time so the temporary file is generated by SELECT
136-
usleep(10_000);
137-
138171
# Kill with SIGKILL
139172
$ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
140173
is($ret, 0, 'killed process with KILL');
141174

142175
# Close psql session
143176
$killme->finish;
177+
$killme2->finish;
144178

145179
# Wait till server restarts
146180
$node->poll_query_until('postgres', 'SELECT 1', '1');

0 commit comments

Comments
 (0)