(new thread) On Tue, Feb 17, 2026 at 03:30:57PM -0600, Nathan Bossart wrote: > On Tue, Feb 17, 2026 at 11:18:00PM +0200, Heikki Linnakangas wrote: >> On 14/02/2026 23:56, Andres Freund wrote: >>> We really need some instrumentation that fails if we do allocations in >>> signal >>> handlers etc. >> >> Yeah, that would be nice.. > > In theory we could pretty easily add assertions for that, given the > wrapper_handler business added a couple of years ago. I'll put together a > patch...
As promised... Fortunately, check-world didn't uncover any existing issues. I was able to manually verify the assertion by switching a background worker to use bgworker_die() and sending it SIGTERM. Probably could use some additional commentary, which I'll add if the idea seems reasonable to you. -- nathan
>From 139f33bcc5ac0fb0e63638fd509eda6a2ad3ddd2 Mon Sep 17 00:00:00 2001 From: Nathan Bossart <[email protected]> Date: Tue, 17 Feb 2026 16:24:12 -0600 Subject: [PATCH v1 1/1] Add an assertion that you don't palloc in a signal handler. --- src/backend/utils/mmgr/mcxt.c | 9 +++++++++ src/include/miscadmin.h | 3 +++ src/port/pqsignal.c | 10 ++++++++++ 3 files changed, 22 insertions(+) diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index 073bdb35d2a..4d79359b0b9 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -1235,6 +1235,7 @@ MemoryContextAlloc(MemoryContext context, Size size) Assert(MemoryContextIsValid(context)); AssertNotInCriticalSection(context); + Assert(!InSignalHandler); context->isReset = false; @@ -1269,6 +1270,7 @@ MemoryContextAllocZero(MemoryContext context, Size size) Assert(MemoryContextIsValid(context)); AssertNotInCriticalSection(context); + Assert(!InSignalHandler); context->isReset = false; @@ -1292,6 +1294,7 @@ MemoryContextAllocExtended(MemoryContext context, Size size, int flags) Assert(MemoryContextIsValid(context)); AssertNotInCriticalSection(context); + Assert(!InSignalHandler); if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) : AllocSizeIsValid(size))) @@ -1392,6 +1395,7 @@ palloc(Size size) Assert(MemoryContextIsValid(context)); AssertNotInCriticalSection(context); + Assert(!InSignalHandler); context->isReset = false; @@ -1422,6 +1426,7 @@ palloc0(Size size) Assert(MemoryContextIsValid(context)); AssertNotInCriticalSection(context); + Assert(!InSignalHandler); context->isReset = false; @@ -1444,6 +1449,7 @@ palloc_extended(Size size, int flags) Assert(MemoryContextIsValid(context)); AssertNotInCriticalSection(context); + Assert(!InSignalHandler); context->isReset = false; @@ -1637,6 +1643,7 @@ repalloc(void *pointer, Size size) void *ret; AssertNotInCriticalSection(context); + Assert(!InSignalHandler); /* isReset must be false already */ Assert(!context->isReset); @@ -1672,6 +1679,7 @@ repalloc_extended(void *pointer, Size size, int flags) void *ret; AssertNotInCriticalSection(context); + Assert(!InSignalHandler); /* isReset must be false already */ Assert(!context->isReset); @@ -1728,6 +1736,7 @@ MemoryContextAllocHuge(MemoryContext context, Size size) Assert(MemoryContextIsValid(context)); AssertNotInCriticalSection(context); + Assert(!InSignalHandler); context->isReset = false; diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index f16f35659b9..a1c89147586 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -155,6 +155,9 @@ do { \ CritSectionCount--; \ } while(0) +/* in port/pqsignal.c */ +extern PGDLLIMPORT volatile sig_atomic_t InSignalHandler; + /***************************************************************************** * globals.h -- * diff --git a/src/port/pqsignal.c b/src/port/pqsignal.c index fbdf9341c2f..6e036975b3c 100644 --- a/src/port/pqsignal.c +++ b/src/port/pqsignal.c @@ -71,6 +71,10 @@ StaticAssertDecl(SIGALRM < PG_NSIG, "SIGALRM >= PG_NSIG"); static volatile pqsigfunc pqsignal_handlers[PG_NSIG]; +#ifndef FRONTEND +volatile sig_atomic_t InSignalHandler = false; +#endif + /* * Except when called with SIG_IGN or SIG_DFL, pqsignal() sets up this function * as the handler for all signals. This wrapper handler function checks that @@ -99,6 +103,8 @@ wrapper_handler(SIGNAL_ARGS) Assert(MyProcPid); Assert(MyProcPid != PostmasterPid || !IsUnderPostmaster); + InSignalHandler = true; + if (unlikely(MyProcPid != (int) getpid())) { pqsignal(postgres_signal_arg, SIG_DFL); @@ -109,6 +115,10 @@ wrapper_handler(SIGNAL_ARGS) (*pqsignal_handlers[postgres_signal_arg]) (postgres_signal_arg); +#ifndef FRONTEND + InSignalHandler = false; +#endif + errno = save_errno; } -- 2.50.1 (Apple Git-155)
