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