|
24 | 24 | }
|
25 | 25 | else
|
26 | 26 | {
|
27 |
| - plan tests => 12; |
| 27 | + plan tests => 18; |
28 | 28 | }
|
29 | 29 |
|
30 | 30 | # To avoid hanging while expecting some specific input from a psql
|
31 | 31 | # instance being driven by us, add a timeout high enough that it
|
32 | 32 | # should never trigger in a normal run, but low enough to actually see
|
33 | 33 | # failures in a realistic amount of time.
|
34 |
| -my $psql_timeout = 180; |
| 34 | +my $psql_timeout = IPC::Run::timer(10); |
35 | 35 |
|
36 | 36 | my $node = get_new_node('master');
|
37 | 37 | $node->init(allows_streaming => 1);
|
|
54 | 54 | \$killme_stdout,
|
55 | 55 | '2>',
|
56 | 56 | \$killme_stderr,
|
57 |
| - IPC::Run::timeout($psql_timeout)); |
| 57 | + $psql_timeout); |
58 | 58 |
|
59 | 59 | # Need a second psql to check if crash-restart happened.
|
60 | 60 | my ($monitor_stdin, $monitor_stdout, $monitor_stderr) = ('', '', '');
|
|
67 | 67 | \$monitor_stdout,
|
68 | 68 | '2>',
|
69 | 69 | \$monitor_stderr,
|
70 |
| - IPC::Run::timeout($psql_timeout)); |
| 70 | + $psql_timeout); |
71 | 71 |
|
72 | 72 | #create table, insert row that should survive
|
73 | 73 | $killme_stdin .= q[
|
74 | 74 | CREATE TABLE alive(status text);
|
75 | 75 | INSERT INTO alive VALUES($$committed-before-sigquit$$);
|
76 | 76 | SELECT pg_backend_pid();
|
77 | 77 | ];
|
78 |
| -$killme->pump until $killme_stdout =~ /[[:digit:]]+[\r\n]$/; |
| 78 | +ok(pump_until($killme, \$killme_stdout, qr/[[:digit:]]+[\r\n]$/m), |
| 79 | + 'acquired pid for SIGQUIT'); |
79 | 80 | my $pid = $killme_stdout;
|
80 | 81 | chomp($pid);
|
81 | 82 | $killme_stdout = '';
|
| 83 | +$killme_stderr = ''; |
82 | 84 |
|
83 | 85 | #insert a row that should *not* survive, due to in-progress xact
|
84 | 86 | $killme_stdin .= q[
|
85 | 87 | BEGIN;
|
86 | 88 | INSERT INTO alive VALUES($$in-progress-before-sigquit$$) RETURNING status;
|
87 | 89 | ];
|
88 |
| -$killme->pump until $killme_stdout =~ /in-progress-before-sigquit/; |
| 90 | +ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigquit/m), |
| 91 | + 'inserted in-progress-before-sigquit'); |
89 | 92 | $killme_stdout = '';
|
| 93 | +$killme_stderr = ''; |
90 | 94 |
|
91 | 95 |
|
92 | 96 | # Start longrunning query in second session, it's failure will signal
|
|
96 | 100 | SELECT $$psql-connected$$;
|
97 | 101 | SELECT pg_sleep(3600);
|
98 | 102 | ];
|
99 |
| -$monitor->pump until $monitor_stdout =~ /psql-connected/; |
100 |
| - |
| 103 | +ok(pump_until($monitor, \$monitor_stdout, qr/psql-connected/m), |
| 104 | + 'monitor connected'); |
| 105 | +$monitor_stdout = ''; |
| 106 | +$monitor_stderr = ''; |
101 | 107 |
|
102 | 108 | # kill once with QUIT - we expect psql to exit, while emitting error message first
|
103 | 109 | my $cnt = kill 'QUIT', $pid;
|
104 | 110 |
|
105 | 111 | # Exactly process should have been alive to be killed
|
106 | 112 | is($cnt, 1, "exactly one process killed with SIGQUIT");
|
107 | 113 |
|
108 |
| -# Check that psql sees the killed backend as having been terminated |
| 114 | +# Check that psql sees the killed backend as having been terminated |
109 | 115 | $killme_stdin .= q[
|
110 | 116 | SELECT 1;
|
111 | 117 | ];
|
112 |
| -$killme->pump until $killme_stderr =~ /WARNING: terminating connection because of crash of another server process/; |
113 |
| - |
114 |
| -ok(1, "psql query died successfully after SIGQUIT"); |
| 118 | +ok(pump_until($killme, \$killme_stderr, qr/WARNING: terminating connection because of crash of another server process/m), |
| 119 | + "psql query died successfully after SIGQUIT"); |
| 120 | +$killme_stderr = ''; |
| 121 | +$killme_stdout = ''; |
115 | 122 | $killme->kill_kill;
|
116 | 123 |
|
117 |
| -# Check if the crash-restart cycle has occurred |
118 |
| -$monitor->pump until $monitor_stderr =~ /WARNING: terminating connection because of crash of another server process/; |
| 124 | +# Wait till server restarts - we should get the WARNING here, but |
| 125 | +# sometimes the server is unable to send that, if interrupted while |
| 126 | +# sending. |
| 127 | +ok(pump_until($monitor, \$monitor_stderr, qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m), |
| 128 | + "psql monitor died successfully after SIGQUIT"); |
119 | 129 | $monitor->kill_kill;
|
120 |
| -ok(1, "psql monitor died successfully after SIGQUIT"); |
121 | 130 |
|
122 | 131 | # Wait till server restarts
|
123 |
| -is($node->poll_query_until('postgres', 'SELECT $$restarted$$;', 'restarted'), "1", "reconnected after SIGQUIT"); |
| 132 | +is($node->poll_query_until('postgres', 'SELECT $$restarted after sigquit$$;', 'restarted after sigquit'), |
| 133 | + "1", "reconnected after SIGQUIT"); |
| 134 | + |
124 | 135 |
|
125 | 136 | # restart psql processes, now that the crash cycle finished
|
126 | 137 | ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', '');
|
|
133 | 144 | $killme_stdin .= q[
|
134 | 145 | SELECT pg_backend_pid();
|
135 | 146 | ];
|
136 |
| -$killme->pump until $killme_stdout =~ /[[:digit:]]+[\r\n]$/; |
| 147 | +ok(pump_until($killme, \$killme_stdout, qr/[[:digit:]]+[\r\n]$/m), |
| 148 | + "acquired pid for SIGKILL"); |
137 | 149 | $pid = $killme_stdout;
|
138 | 150 | chomp($pid);
|
139 | 151 | $pid = $killme_stdout;
|
| 152 | +$killme_stdout = ''; |
| 153 | +$killme_stderr = ''; |
140 | 154 |
|
141 | 155 | # Insert test rows
|
142 | 156 | $killme_stdin .= q[
|
143 | 157 | INSERT INTO alive VALUES($$committed-before-sigkill$$) RETURNING status;
|
144 | 158 | BEGIN;
|
145 | 159 | INSERT INTO alive VALUES($$in-progress-before-sigkill$$) RETURNING status;
|
146 | 160 | ];
|
147 |
| -$killme->pump until $killme_stdout =~ /in-progress-before-sigkill/; |
| 161 | +ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m), |
| 162 | + 'inserted in-progress-before-sigkill'); |
148 | 163 | $killme_stdout = '';
|
| 164 | +$killme_stderr = ''; |
149 | 165 |
|
150 | 166 | # Re-start longrunning query in second session, it's failure will
|
151 | 167 | # signal that crash-restart has occurred. The initial wait for the
|
|
155 | 171 | SELECT $$psql-connected$$;
|
156 | 172 | SELECT pg_sleep(3600);
|
157 | 173 | ];
|
158 |
| -$monitor->pump until $monitor_stdout =~ /psql-connected/; |
| 174 | +ok(pump_until($monitor, \$monitor_stdout, qr/psql-connected/m), |
| 175 | + 'monitor connected'); |
159 | 176 | $monitor_stdout = '';
|
| 177 | +$monitor_stderr = ''; |
160 | 178 |
|
161 | 179 |
|
162 | 180 | # kill with SIGKILL this time - we expect the backend to exit, without
|
|
169 | 187 | $killme_stdin .= q[
|
170 | 188 | SELECT 1;
|
171 | 189 | ];
|
172 |
| -$killme->pump until $killme_stderr =~ /server closed the connection unexpectedly/; |
| 190 | +ok(pump_until($killme, \$killme_stderr, qr/server closed the connection unexpectedly/m), |
| 191 | + "psql query died successfully after SIGKILL"); |
173 | 192 | $killme->kill_kill;
|
174 |
| -ok(1, "psql query died successfully after SIGKILL"); |
175 | 193 |
|
176 |
| -# Wait till server restarts (note that we should get the WARNING here) |
177 |
| -$monitor->pump until $monitor_stderr =~ /WARNING: terminating connection because of crash of another server process/; |
178 |
| -ok(1, "psql monitor died successfully after SIGKILL"); |
| 194 | +# Wait till server restarts - we should get the WARNING here, but |
| 195 | +# sometimes the server is unable to send that, if interrupted while |
| 196 | +# sending. |
| 197 | +ok(pump_until($monitor, \$monitor_stderr, qr/WARNING: terminating connection because of crash of another server process|server closed the connection unexpectedly/m), |
| 198 | + "psql monitor died successfully after SIGKILL"); |
179 | 199 | $monitor->kill_kill;
|
180 | 200 |
|
181 | 201 | # Wait till server restarts
|
|
198 | 218 | 'after-orderly-restart', 'can still write after orderly restart');
|
199 | 219 |
|
200 | 220 | $node->stop();
|
| 221 | + |
| 222 | +# Pump until string is matched, or timeout occurs |
| 223 | +sub pump_until |
| 224 | +{ |
| 225 | + my ($proc, $stream, $untl) = @_; |
| 226 | + $proc->pump_nb(); |
| 227 | + while (1) |
| 228 | + { |
| 229 | + if ($psql_timeout->is_expired) |
| 230 | + { |
| 231 | + diag("aborting wait: program timed out"); |
| 232 | + diag("stream contents: >>", $$stream,"<<"); |
| 233 | + diag("pattern searched for: ", $untl); |
| 234 | + |
| 235 | + return 0; |
| 236 | + } |
| 237 | + if (not $proc->pumpable()) |
| 238 | + { |
| 239 | + diag("aborting wait: program died"); |
| 240 | + diag("stream contents: >>", $$stream,"<<"); |
| 241 | + diag("pattern searched for: ", $untl); |
| 242 | + |
| 243 | + return 0; |
| 244 | + } |
| 245 | + $proc->pump(); |
| 246 | + last if $$stream =~ /$untl/; |
| 247 | + } |
| 248 | + return 1; |
| 249 | + |
| 250 | +}; |
0 commit comments