On Fri, Jul 15, 2022 at 3:27 AM Tom Lane <t...@sss.pgh.pa.us> wrote:
> Alvaro Herrera <alvhe...@alvh.no-ip.org> writes:
> > ISTM it would be cleaner to patch PG_SETMASK to have a second argument
> > and to return the original mask if that's not NULL.  This is more
> > invasive, but there aren't that many callsites of that macro.
>
> [ shoulda read your message before replying ]
>
> Given that this needs back-patched, I think changing PG_SETMASK
> is a bad idea: there might be outside callers.  However, we could
> add another macro with the additional argument.  PG_GET_AND_SET_MASK?

It's funny though, the reason we had PG_SETMASK in the first place is
not for Windows.  Ancient commit 47937403676 added that for long gone
pre-POSIX systems like NeXTSTEP which only had single-argument
sigsetmask(), not sigprocmask().  In general on Windows we're
emulating POSIX signal interfaces with normal names like sigemptyset()
etc, it just so happens that we chose to emulate that pre-standard
sigsetmask() interface (as you complained about in the commit message
for a65e0864).

So why would I add another wrapper like PG_SETMASK and leave it
unimplemented for now on Windows, when I could just use sigprocmask()
directly and leave it unimplemented for now on Windows?

The only reason I can think of for a wrapper is to provide a place to
check the return code and ereport (panic?).  That seems to be of
limited value (how can it fail ... bad "how" value, or a sandbox
denying some system calls, ...?).  I did make sure to preserve the
errno though; even though we're assuming these calls can't fail by
long standing tradition, I didn't feel like additionally assuming that
successful calls don't clobber errno.

I guess, coded like this, it should also be safe to do it in the
postmaster, but I think maybe we should leave it conditional, rather
than relying on BlockSig being initialised and sane during early
postmaster initialisation.
From 17eb588af303873dbd76d0f24b536f74747cb3bf Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.mu...@gmail.com>
Date: Fri, 15 Jul 2022 09:00:12 +1200
Subject: [PATCH] Make dsm_impl_resize more future-proof.

Commit 4518c798 blocks signals for a short region of code, but it
assumed that whatever calls it had the mask set to UnBlockSig on entry.
That may be true today, but it would be more resilient to save and
restore the caller's signal mask.

Previously we couldn't do this because our macro for abstracting signal
mask changes was based on the old pre-POSIX sigsetmask(), due to 1990s
portability concerns.  Since this is a POSIX-only code path, and since
a65e0864 established that supported Unix systems must have
sigprocmask(), we can just use sigprocmask() directly.  It would also be
implementable for Windows, but that's not needed for this.

Back-patch to all releases, like 4518c798 and 80845b7c.

Reviewed-by: Alvaro Herrera <alvhe...@alvh.no-ip.org>
Reviewed-by: Tom Lane <t...@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CA%2BhUKGKx6Biq7_UuV0kn9DW%2B8QWcpJC1qwhizdtD9tN-fn0H0g%40mail.gmail.com
---
 src/backend/storage/ipc/dsm_impl.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 0247d13a91..69c6df75b4 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -49,6 +49,7 @@
 #include "postgres.h"
 
 #include <fcntl.h>
+#include <signal.h>
 #include <unistd.h>
 #ifndef WIN32
 #include <sys/mman.h>
@@ -62,7 +63,7 @@
 #endif
 
 #include "common/file_perm.h"
-#include "libpq/pqsignal.h"		/* for PG_SETMASK macro */
+#include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "pgstat.h"
 #include "portability/mem.h"
@@ -355,6 +356,7 @@ dsm_impl_posix_resize(int fd, off_t size)
 {
 	int			rc;
 	int			save_errno;
+	sigset_t	save_sigmask;
 
 	/*
 	 * Block all blockable signals, except SIGQUIT.  posix_fallocate() can run
@@ -363,7 +365,7 @@ dsm_impl_posix_resize(int fd, off_t size)
 	 * conflicts), the retry loop might never succeed.
 	 */
 	if (IsUnderPostmaster)
-		PG_SETMASK(&BlockSig);
+		sigprocmask(SIG_SETMASK, &BlockSig, &save_sigmask);
 
 	pgstat_report_wait_start(WAIT_EVENT_DSM_ALLOCATE);
 #if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
@@ -402,7 +404,7 @@ dsm_impl_posix_resize(int fd, off_t size)
 	if (IsUnderPostmaster)
 	{
 		save_errno = errno;
-		PG_SETMASK(&UnBlockSig);
+		sigprocmask(SIG_SETMASK, &save_sigmask, NULL);
 		errno = save_errno;
 	}
 
-- 
2.30.2

Reply via email to