|
5 | 5 | use TestLib;
|
6 | 6 | use Test::More;
|
7 | 7 | use Config;
|
8 |
| -use Time::HiRes qw(usleep); |
9 | 8 |
|
10 | 9 | plan tests => 9;
|
11 | 10 |
|
|
33 | 32 | # create table, insert rows
|
34 | 33 | $node->safe_psql(
|
35 | 34 | '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);]); |
38 | 36 |
|
39 | 37 | # Run psql, keeping session alive, so we have an alive backend to kill.
|
40 | 38 | my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', '');
|
|
62 | 60 | $killme_stdout = '';
|
63 | 61 | $killme_stderr = '';
|
64 | 62 |
|
| 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 | + |
65 | 89 | # Run the query that generates a temporary file and that will be killed before
|
66 | 90 | # it finishes. Since the query that generates the temporary file does not
|
67 | 91 | # return before the connection is killed, use a SELECT before to trigger
|
68 | 92 | # pump_until.
|
69 | 93 | $killme_stdin .= q[
|
70 | 94 | BEGIN;
|
71 | 95 | 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); |
73 | 97 | ];
|
74 | 98 | ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
|
75 |
| - 'select in-progress-before-sigkill'); |
| 99 | + 'insert in-progress-before-sigkill'); |
76 | 100 | $killme_stdout = '';
|
77 | 101 | $killme_stderr = '';
|
78 | 102 |
|
79 |
| -# Wait some time so the temporary file is generated by SELECT |
80 |
| -usleep(10_000); |
81 |
| - |
82 | 103 | # Kill with SIGKILL
|
83 | 104 | my $ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
|
84 | 105 | is($ret, 0, 'killed process with KILL');
|
85 | 106 |
|
86 | 107 | # Close psql session
|
87 | 108 | $killme->finish;
|
| 109 | +$killme2->finish; |
88 | 110 |
|
89 | 111 | # Wait till server restarts
|
90 | 112 | $node->poll_query_until('postgres', 'SELECT 1', '1');
|
|
118 | 140 | $killme_stdout = '';
|
119 | 141 | $killme_stderr = '';
|
120 | 142 |
|
| 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 | + |
121 | 157 | # Run the query that generates a temporary file and that will be killed before
|
122 | 158 | # it finishes. Since the query that generates the temporary file does not
|
123 | 159 | # return before the connection is killed, use a SELECT before to trigger
|
124 | 160 | # pump_until.
|
125 | 161 | $killme_stdin .= q[
|
126 | 162 | BEGIN;
|
127 | 163 | 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); |
129 | 165 | ];
|
130 | 166 | ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m),
|
131 |
| - 'select in-progress-before-sigkill'); |
| 167 | + 'insert in-progress-before-sigkill'); |
132 | 168 | $killme_stdout = '';
|
133 | 169 | $killme_stderr = '';
|
134 | 170 |
|
135 |
| -# Wait some time so the temporary file is generated by SELECT |
136 |
| -usleep(10_000); |
137 |
| - |
138 | 171 | # Kill with SIGKILL
|
139 | 172 | $ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid);
|
140 | 173 | is($ret, 0, 'killed process with KILL');
|
141 | 174 |
|
142 | 175 | # Close psql session
|
143 | 176 | $killme->finish;
|
| 177 | +$killme2->finish; |
144 | 178 |
|
145 | 179 | # Wait till server restarts
|
146 | 180 | $node->poll_query_until('postgres', 'SELECT 1', '1');
|
|
0 commit comments