v1-0010-pg_dump-Block-signals-during-signal-handler.patch
text/x-patch
Filename: v1-0010-pg_dump-Block-signals-during-signal-handler.patch
Type: text/x-patch
Part: 9
Message:
pg_threads.h take II
Patch
Format: format-patch
Series: patch v1-0010
Subject: pg_dump: Block signals during signal handler.
| File | + | − |
|---|---|---|
| src/bin/pg_dump/parallel.c | 17 | 13 |
From 6fc445954b8d2e64613124cef6583fc96aa617f9 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 4 Jul 2026 17:21:50 +1200
Subject: [PATCH v1 10/14] pg_dump: Block signals during signal handler.
Previously we tried to avoid running the cancellation handler more than
once by setting SIGINT, SIGQUIT, SIGTERM to SIG_IGN at the top of the
handler. Let's just block them with sa_mask, to achieve the same thing
without races.
While it's unlikely that repeated cancellation would really be a
problem, and PQcancel() surely has to be reentrant, it's still nice to
remove comments about ancient pre-standard Unix problems that have long
been solved.
Discussion:
Reviewed-by:
---
src/bin/pg_dump/parallel.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/src/bin/pg_dump/parallel.c b/src/bin/pg_dump/parallel.c
index 2381fa405ba..81d0865284d 100644
--- a/src/bin/pg_dump/parallel.c
+++ b/src/bin/pg_dump/parallel.c
@@ -545,20 +545,11 @@ WaitForTerminatingWorkers(ParallelState *pstate)
* Signal handler (Unix only)
*/
static void
-sigTermHandler(SIGNAL_ARGS)
+sigTermHandler(int signo)
{
int i;
char errbuf[1];
- /*
- * Some platforms allow delivery of new signals to interrupt an active
- * signal handler. That could muck up our attempt to send PQcancel, so
- * disable the signals that set_cancel_handler enabled.
- */
- pqsignal(SIGINT, PG_SIG_IGN);
- pqsignal(SIGTERM, PG_SIG_IGN);
- pqsignal(SIGQUIT, PG_SIG_IGN);
-
/*
* If we're in the leader, forward signal to all workers. (It seems best
* to do this before PQcancel; killing the leader transaction will result
@@ -616,11 +607,24 @@ set_cancel_handler(void)
*/
if (!signal_info.handler_set)
{
+ struct sigaction sa = {0};
+
signal_info.handler_set = true;
- pqsignal(SIGINT, sigTermHandler);
- pqsignal(SIGTERM, sigTermHandler);
- pqsignal(SIGQUIT, sigTermHandler);
+ /*
+ * While any of these signals is handled, block all three to avoid
+ * possible repeat cancellation.
+ */
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGINT);
+ sigaddset(&sa.sa_mask, SIGTERM);
+ sigaddset(&sa.sa_mask, SIGQUIT);
+
+ sa.sa_handler = sigTermHandler;
+
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGQUIT, &sa, NULL);
}
}
--
2.47.3