On Thu, Mar 18, 2021, at 8:34 PM, Tomas Vondra wrote:
> Well, that's better, bit it still does not do the trick on the 32-bit
> machine - in that case a 1000 rows with int4 still fit into work_mem, so
> the temp file is not created. Per my experiments about 1040 rows are
> needed - soooo close ;-) So let's make it 2000.
My 32-bit laptop needs some repairs so I blindly chose 1k rows.
> We might as well check that the temp file actually exists, before
> killing the backend. Just to be sure.
Do you mean with remove_temp_files_after_crash = on? New version attached.
--
Euler Taveira
EDB https://www.enterprisedb.com/
diff --git a/src/test/recovery/t/022_crash_temp_files.pl b/src/test/recovery/t/022_crash_temp_files.pl
index c37b227770..38e935d641 100644
--- a/src/test/recovery/t/022_crash_temp_files.pl
+++ b/src/test/recovery/t/022_crash_temp_files.pl
@@ -5,9 +5,8 @@ use PostgresNode;
use TestLib;
use Test::More;
use Config;
-use Time::HiRes qw(usleep);
-plan tests => 9;
+plan tests => 10;
# To avoid hanging while expecting some specific input from a psql
@@ -33,8 +32,7 @@ $node->safe_psql(
# create table, insert rows
$node->safe_psql(
'postgres',
- q[CREATE TABLE tab_crash (a text);
- INSERT INTO tab_crash (a) SELECT gen_random_uuid() FROM generate_series(1, 500);]);
+ q[CREATE TABLE tab_crash (a integer UNIQUE);]);
# Run psql, keeping session alive, so we have an alive backend to kill.
my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', '');
@@ -62,6 +60,32 @@ chomp($pid);
$killme_stdout = '';
$killme_stderr = '';
+# Open a 2nd session that will block the 1st session. The UNIQUE constraint
+# will prevent the temporary file from the 1st session to be removed.
+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
# it finishes. Since the query that generates the temporary file does not
# return before the connection is killed, use a SELECT before to trigger
@@ -69,15 +93,18 @@ $killme_stderr = '';
$killme_stdin .= q[
BEGIN;
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, 2000) s(i);
];
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_stderr = '';
-# Wait some time so the temporary file is generated by SELECT
-usleep(10_000);
+# Check for the existence of a temporary file
+is($node->safe_psql(
+ 'postgres',
+ 'SELECT COUNT(1) FROM pg_ls_dir($$base/pgsql_tmp$$)'),
+ qq(1), 'one temporary file');
# Kill with SIGKILL
my $ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
@@ -85,6 +112,7 @@ is($ret, 0, 'killed process with KILL');
# Close psql session
$killme->finish;
+$killme2->finish;
# Wait till server restarts
$node->poll_query_until('postgres', 'SELECT 1', '1');
@@ -118,6 +146,20 @@ chomp($pid);
$killme_stdout = '';
$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
# it finishes. Since the query that generates the temporary file does not
# return before the connection is killed, use a SELECT before to trigger
@@ -125,22 +167,20 @@ $killme_stderr = '';
$killme_stdin .= q[
BEGIN;
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, 2000) s(i);
];
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_stderr = '';
-# Wait some time so the temporary file is generated by SELECT
-usleep(10_000);
-
# Kill with SIGKILL
$ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
is($ret, 0, 'killed process with KILL');
# Close psql session
$killme->finish;
+$killme2->finish;
# Wait till server restarts
$node->poll_query_until('postgres', 'SELECT 1', '1');