Skip to content

Commit b9f39d0

Browse files
committed
fix: preventing DROP DATABASE from completing
When doing `CREATE DATABASE foo` and then `DROP DATABASE foo`, the command stuck waiting showing: ``` 2025-07-30 08:29:22.191 -05 [265233] LOG: still waiting for backend with PID 265223 to accept ProcSignalBarrier ... ``` This happened because DROP DATABASE sends a SIGUSR1 to all backends and we use the potsgres default SIGUSR1 handler (`procsignal_sigusr1_handler`), which didn't wake the worker to reach `CHECK_FOR_INTERRUPTS()`. Now we use a custom sigusr1 that does `SetLatch` (waking the worker) and calls the default pg SIGUSR1 handler.
1 parent a78be08 commit b9f39d0

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

src/worker.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,22 @@ handle_sighup(__attribute__ ((unused)) SIGNAL_ARGS)
139139
errno = save_errno;
140140
}
141141

142+
/*
143+
*We have to handle sigusr1 explicitly because the default
144+
*procsignal_sigusr1_handler doesn't `SetLatch`, this would prevent
145+
*DROP DATATABASE from finishing since our worker would be sleeping and not reach
146+
*CHECK_FOR_INTERRUPTS()
147+
*/
148+
static void
149+
handle_sigusr1(SIGNAL_ARGS)
150+
{
151+
int save_errno = errno;
152+
if (worker_state)
153+
SetLatch(&worker_state->latch);
154+
errno = save_errno;
155+
procsignal_sigusr1_handler(postgres_signal_arg);
156+
}
157+
142158
static void publish_state(WorkerStatus s) {
143159
pg_atomic_write_u32(&worker_state->status, (uint32)s);
144160
pg_write_barrier();
@@ -219,7 +235,7 @@ void pg_net_worker(__attribute__ ((unused)) Datum main_arg) {
219235
BackgroundWorkerUnblockSignals();
220236
pqsignal(SIGTERM, handle_sigterm);
221237
pqsignal(SIGHUP, handle_sighup);
222-
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
238+
pqsignal(SIGUSR1, handle_sigusr1);
223239

224240
BackgroundWorkerInitializeConnection(guc_database_name, guc_username, 0);
225241
pgstat_report_appname("pg_net " EXTVERSION); // set appname for pg_stat_activity

test/test_worker_behavior.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@
77
import subprocess
88
import os
99

10+
def test_worker_will_not_block_drop_database(autocommit_sess):
11+
"""the worker will not block a session doing drop database"""
12+
13+
autocommit_sess.execute(text("create database foo;"))
14+
autocommit_sess.execute(text("drop database foo;"))
15+
16+
(result,) = autocommit_sess.execute(text("""
17+
select 1
18+
""")).fetchone()
19+
20+
assert result is not None
21+
assert result == 1
22+
23+
1024
def test_success_when_worker_is_up(sess):
1125
"""net.check_worker_is_up should not return anything when the worker is running"""
1226

@@ -433,3 +447,4 @@ def test_processing_survives_postmaster_crash():
433447
tmp_sess.execute(text("select net.wait_until_running()"))
434448

435449
engine.dispose()
450+

0 commit comments

Comments
 (0)