On Fri, Jul 15, 2022 at 9:34 AM Tom Lane <t...@sss.pgh.pa.us> wrote:
> (Someday we oughta go ahead and make our Windows signal API look more
> like POSIX, as I suggested back in 2015.  I'm still not taking
> point on that, though.)

For the sigprocmask() part, here's a patch that passes CI.  Only the
SIG_SETMASK case is actually exercised by our current code, though.

One weird thing about our PG_SETMASK() macro is that you couldn't have
used its return value portably: on Windows we were returning the old
mask (like sigsetmask(), which has no way to report errors), and on
Unix we were returning 0/-1 (from setprocmask(), ie the error we never
checked).
From b21140e9b3f593b46c3bb4782c6bf84ca248dc15 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.mu...@gmail.com>
Date: Fri, 15 Jul 2022 14:35:01 +1200
Subject: [PATCH] Emulate sigprocmask(), not sigsetmask(), on Windows.

Since commit a65e0864, we've required Unix systems to have
sigprocmask().  For Windows we still emulated the old deprecated 4.2BSD
function sigsetmask().  Emulate sigprocmask() instead, for consistency.

Discussion: https://postgr.es/m/3153247.1657834482%40sss.pgh.pa.us
---
 src/backend/port/win32/signal.c | 29 +++++++++++++++++++++++------
 src/include/libpq/pqsignal.h    | 11 +++++++----
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/src/backend/port/win32/signal.c b/src/backend/port/win32/signal.c
index b71164d8db..53b93a50b2 100644
--- a/src/backend/port/win32/signal.c
+++ b/src/backend/port/win32/signal.c
@@ -112,7 +112,7 @@ pgwin32_signal_initialize(void)
 /*
  * Dispatch all signals currently queued and not blocked
  * Blocked signals are ignored, and will be fired at the time of
- * the pqsigsetmask() call.
+ * the pqsigprocmask() call.
  */
 void
 pgwin32_dispatch_queued_signals(void)
@@ -154,12 +154,29 @@ pgwin32_dispatch_queued_signals(void)
 
 /* signal masking. Only called on main thread, no sync required */
 int
-pqsigsetmask(int mask)
+pqsigprocmask(int how, const sigset_t *set, sigset_t *oset)
 {
-	int			prevmask;
+	if (oset)
+		*oset = pg_signal_mask;
 
-	prevmask = pg_signal_mask;
-	pg_signal_mask = mask;
+	if (!set)
+		return 0;
+
+	switch (how)
+	{
+		case SIG_BLOCK:
+			pg_signal_mask |= *set;
+			break;
+		case SIG_UNBLOCK:
+			pg_signal_mask &= ~*set;
+			break;
+		case SIG_SETMASK:
+			pg_signal_mask = *set;
+			break;
+		default:
+			errno = EINVAL;
+			return -1;
+	}
 
 	/*
 	 * Dispatch any signals queued up right away, in case we have unblocked
@@ -167,7 +184,7 @@ pqsigsetmask(int mask)
 	 */
 	pgwin32_dispatch_queued_signals();
 
-	return prevmask;
+	return 0;
 }
 
 
diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h
index 41227a30e2..d17ddb787e 100644
--- a/src/include/libpq/pqsignal.h
+++ b/src/include/libpq/pqsignal.h
@@ -15,15 +15,18 @@
 
 #include <signal.h>
 
-#ifndef WIN32
 #define PG_SETMASK(mask)	sigprocmask(SIG_SETMASK, mask, NULL)
-#else
+
+#ifdef WIN32
 /* Emulate POSIX sigset_t APIs on Windows */
 typedef int sigset_t;
 
-extern int	pqsigsetmask(int mask);
+extern int	pqsigprocmask(int how, const sigset_t *set, sigset_t *oset);
 
-#define PG_SETMASK(mask)		pqsigsetmask(*(mask))
+#define SIG_BLOCK				1
+#define SIG_UNBLOCK				2
+#define SIG_SETMASK				3
+#define sigprocmask(how, set, oset) pqsigprocmask((how), (set), (oset))
 #define sigemptyset(set)		(*(set) = 0)
 #define sigfillset(set)			(*(set) = ~0)
 #define sigaddset(set, signum)	(*(set) |= (sigmask(signum)))
-- 
2.36.1

Reply via email to