|
88 | 88 | # Test that interruption of DROP DATABASE is handled properly. To ensure the
|
89 | 89 | # interruption happens at the appropriate moment, we lock pg_tablespace. DROP
|
90 | 90 | # DATABASE scans pg_tablespace once it has reached the "irreversible" part of
|
91 |
| -# dropping the database, making it a suitable point to wait. |
| 91 | +# dropping the database, making it a suitable point to wait. Since relcache |
| 92 | +# init reads pg_tablespace, establish each connection before locking. This |
| 93 | +# avoids a connection-time hang with debug_discard_caches. |
| 94 | +my $cancel = $node->background_psql('postgres', on_error_stop => 1); |
92 | 95 | my $bgpsql = $node->background_psql('postgres', on_error_stop => 0);
|
93 | 96 | my $pid = $bgpsql->query('SELECT pg_backend_pid()');
|
94 | 97 |
|
|
104 | 107 | # Try to drop. This will wait due to the still held lock.
|
105 | 108 | $bgpsql->query_until(qr//, "DROP DATABASE regression_invalid_interrupt;\n");
|
106 | 109 |
|
107 |
| -# Ensure we're waiting for the lock |
108 |
| -$node->poll_query_until('postgres', |
109 |
| - qq(SELECT EXISTS(SELECT * FROM pg_locks WHERE NOT granted AND relation = 'pg_tablespace'::regclass AND mode = 'AccessShareLock');) |
110 |
| -); |
111 | 110 |
|
112 |
| -# and finally interrupt the DROP DATABASE |
113 |
| -ok($node->safe_psql('postgres', "SELECT pg_cancel_backend($pid)"), |
| 111 | +# Once the DROP DATABASE is waiting for the lock, interrupt it. |
| 112 | +ok( $cancel->query_safe( |
| 113 | + qq( |
| 114 | + DO \$\$ |
| 115 | + BEGIN |
| 116 | + WHILE NOT EXISTS(SELECT * FROM pg_locks WHERE NOT granted AND relation = 'pg_tablespace'::regclass AND mode = 'AccessShareLock') LOOP |
| 117 | + PERFORM pg_sleep(.1); |
| 118 | + END LOOP; |
| 119 | + END\$\$; |
| 120 | + SELECT pg_cancel_backend($pid);)), |
114 | 121 | "canceling DROP DATABASE");
|
| 122 | +$cancel->quit(); |
115 | 123 |
|
116 | 124 | # wait for cancellation to be processed
|
117 | 125 | ok( pump_until(
|
|
120 | 128 | "cancel processed");
|
121 | 129 | $bgpsql->{stderr} = '';
|
122 | 130 |
|
123 |
| -# verify that connection to the database aren't allowed |
| 131 | +# Verify that connections to the database aren't allowed. The backend checks |
| 132 | +# this before relcache init, so the lock won't interfere. |
124 | 133 | is($node->psql('regression_invalid_interrupt', ''),
|
125 | 134 | 2, "can't connect to invalid_interrupt database");
|
126 | 135 |
|
|
0 commit comments