Don't use __builtin_setjmp on aarch64 MinGW/Windows

Started by Greg Burd28 days ago5 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

appliessuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253227
psql -h localhost -U postgres

Built from patchset v1 (message #1), August 25, 2026 at 05:29 AM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253227_1 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253227_1 && git checkout t253227_1

Patchset v1 (message #1) is on t253227_1

Jump to latest
#1Greg Burd
greg@burd.me

Hello fellow hackers!

My build farm animal "unicorn" has been sick for a while, apologies
for not jumping on that sooner, I'll get to that in another email.

This is a small issue that I found when trying to expand the testing
on my Windows/aarch64 host with two more animals, one for MSYS2 clang
and one with MinGW and gcc. This report/fix is fairly straight
forward in that it is a simple change in c.h for the MSYS2/clang on
aarch64 combo only.

I found that the build fails to compile as early as
src/common/pg_get_line.c, the first caller of sigsetjmp():

../pgsql/src/common/pg_get_line.c:129: error: incompatible pointer
types passing 'sigjmp_buf' (aka 'long long[5]') to parameter of
type 'void **' [-Wincompatible-pointer-types]

and, with a slightly different clang, the more fundamental:

error: __builtin_setjmp is not supported for the current target

Root cause
----------
c.h maps sigsetjmp()/siglongjmp() onto the gcc builtins for MinGW-64:

#ifdef WIN32
#ifdef __MINGW64__
typedef intptr_t sigjmp_buf[5];
#define sigsetjmp(x,y) __builtin_setjmp(x)
#define siglongjmp __builtin_longjmp
#else
...

This dates to commit 146cb3889c3 ("Work around issues in MinGW-64's
setjmp/longjmp support.", 2021), which was written for and tested on
x86_64 MinGW, where __builtin_setjmp works. On aarch64 MinGW
toolchains it does not:

* clang for aarch64-w64-windows-gnu does not implement
__builtin_setjmp at all; and

* where a builtin is accepted, its first parameter is a void **,
which is incompatible with the intptr_t sigjmp_buf[5] that the
same block declares.

So __MINGW64__ is too broad a condition: the builtin-setjmp workaround
is correct on x86_64 MinGW but wrong on aarch64 MinGW.

The underlying MinGW-64 setjmp bug that 146cb3889c3 works around is, as
far as I can tell, still unfixed: the attempt to narrow the workaround
to MSVCRT-only (c313fa4602d, "Use workaround of __builtin_setjmp only on
MINGW on MSVCRT") was reverted by 8f5e419484c because the problem "is
found to cause issues on x86_64 Windows even when using UCRT." So we
should keep the __builtin_setjmp path for x86_64 MinGW; this patch only
removes it where the builtin cannot be used at all.

Fix
---
Restrict the __builtin_setjmp path to !defined(__aarch64__), so that
aarch64 MinGW falls back to plain setjmp()/longjmp() -- the same path
already used for non-MinGW Windows toolchains. x86_64 MinGW is
unchanged.

I tested this fix on my host with the proposed changes and can confirm
that it fixes the issue and that the 2021 defect was GCC-x86_64-MinGW
specific.

Testing
-------
Built and tested on real aarch64 Windows 11 hardware with the MSYS2
clangarm64 toolchain (clang 22.1.8, target aarch64-w64-windows-gnu):

* Without the patch the tree fails to compile at
src/common/pg_get_line.c (the first sigsetjmp() caller), as above.

* With the patch the full tree builds cleanly (ninja: 2103/2103
targets, postgres.exe produced) and, importantly, the resulting
server exercises the setjmp/longjmp path correctly at runtime:
initdb succeeds; 25 consecutive elog(ERROR) cycles (each a
siglongjmp back to the main loop) are caught and recovered; nested
PL/pgSQL exception blocks work; the server stays healthy with no
TRAP/PANIC/crash in the log across the run.

So on this toolchain the plain setjmp()/longjmp() fallback is not merely
a compile fix -- it is runtime-correct. The original MinGW-64
setjmp/longjmp defect that 146cb3889c3 works around appears to be
specific to the x86_64 GCC MinGW toolchain and not present in
clang-aarch64-mingw, which has its own setjmp lowering. I have not
tested a GCC-based aarch64 MinGW toolchain.

I have not exercised a full check-world on this platform yet (that is
gated on a separate atomics issue I am handling in a different thread);
this result is initdb + targeted error-path testing, not the full
regression suite.

The patch is attached (v1). It applies on master and is a one-line
condition change plus a comment update; it changes no behavior on any
currently-supported platform (only aarch64 MinGW, which does not build
today, takes the new path). As is becoming more and more common, yes
I did use AI/LLMs to help diagnose, propose a fix, exhaustively test,
and write this email. I have reviewed the results, the patch, the
tests, and the email content myself and feel that this is a small but
important change that allows for use of Postgres on Windows 11 built
using MSYS2/clang on aarch64 hosts.

best,

-greg

Attachments:

t253227_1
v1-0001-c-h-no-builtin-setjmp-on-aarch64-mingw.patchtext/x-patch; name="=?UTF-8?Q?v1-0001-c-h-no-builtin-setjmp-on-aarch64-mingw.patch?="Download+9-5
#2Nathan Bossart
nathandbossart@gmail.com
In reply to: Greg Burd (#1)
Re: Don't use __builtin_setjmp on aarch64 MinGW/Windows

On Tue, Jul 28, 2026 at 09:10:54AM -0400, Greg Burd wrote:

* clang for aarch64-w64-windows-gnu does not implement
__builtin_setjmp at all; and

Does clang for x86-64 implement it?

So on this toolchain the plain setjmp()/longjmp() fallback is not merely
a compile fix -- it is runtime-correct. The original MinGW-64
setjmp/longjmp defect that 146cb3889c3 works around appears to be
specific to the x86_64 GCC MinGW toolchain and not present in
clang-aarch64-mingw, which has its own setjmp lowering. I have not
tested a GCC-based aarch64 MinGW toolchain.

Testing on aarch64/gcc/mingw seems like an important step.

--
nathan

#3Greg Burd
greg@burd.me
In reply to: Nathan Bossart (#2)
Re: Don't use __builtin_setjmp on aarch64 MinGW/Windows

On Tue, Jul 28, 2026, at 11:35 AM, Nathan Bossart wrote:

On Tue, Jul 28, 2026 at 09:10:54AM -0400, Greg Burd wrote:

* clang for aarch64-w64-windows-gnu does not implement
__builtin_setjmp at all; and

Does clang for x86-64 implement it?

Yes. I checked clang 22.1.8 across a range of targets by compiling

int test(void) {
void *buf[5];
if (__builtin_setjmp(buf)) return 1;
__builtin_longjmp(buf, 1);
return 0;
}

target __builtin_setjmp
------------------------- ----------------
x86_64-pc-linux-gnu compiles
x86_64-w64-windows-gnu compiles
aarch64-linux-gnu error: not supported for the current target
aarch64-w64-windows-gnu error: not supported for the current target
aarch64-pc-windows-msvc error: not supported for the current target
arm64-apple-darwin error: not supported for the current target

So it is not MinGW- or Windows-specific: clang implements
__builtin_setjmp/__builtin_longjmp for x86-64 but rejects it on *every*
aarch64 target I tried, including aarch64-linux and arm64-darwin, with
the same "not supported for the current target" diagnostic. In LLVM
these builtins lower to the EH_SjLj intrinsics, which have target
support on x86 but not on AArch64; it's an architecture-level gap in the
backend, not a property of the MinGW runtime.

That is actually reassuring for the patch's scope: the reason we only
hit this on aarch64 MinGW (and not, say, aarch64 Linux) is simply that
the c.h block that reaches for the builtins is guarded by WIN32 &&
__MINGW64__. On aarch64 Linux we never take the builtin path in the
first place; on aarch64 MinGW we do, and it doesn't compile. Restricting
that path to !defined(__aarch64__) lines aarch64 MinGW up with the plain
setjmp()/longjmp() that every other non-x86_64-MinGW toolchain already
uses.

Testing on aarch64/gcc/mingw seems like an important step.

Agreed, and I want to be upfront that I have not been able to test that
combination yet -- I don't currently have an aarch64 GCC MinGW toolchain
(the llvm-mingw / MSYS2 clangarm64 toolchain I build with is clang-based,
which is where the aarch64 buildfarm work has been happening). So the
runtime evidence I offered ("25/25 elog(ERROR)->siglongjmp cycles, nested
PL/pgSQL exceptions, no crash") is specifically for clang-aarch64-mingw,
whose setjmp lowering is its own thing. I should not have implied
anything broader.

The relevant question your ask raises is: on aarch64 GCC MinGW, does GCC
even implement __builtin_setjmp (so the current code would compile there),
and if so, does the original MinGW-64 setjmp defect from 146cb3889c3
manifest on aarch64 the way it does on x86_64? I can't answer that
without the toolchain. There seem to be two reasonable paths:

1. Keep the patch conservative as written: it only changes
aarch64 MinGW, where clang can't compile the builtin at all, and it
matches what non-MinGW Windows already does. If a GCC aarch64
MinGW build later turns out to need the builtins (i.e. GCC does
implement them there AND the plain-setjmp defect recurs on
aarch64), that would be a follow-up refinement of the condition
(e.g. gate on the compiler as well as the arch), not a reason to
hold this.

2. Hold until someone can stand up aarch64 GCC MinGW and confirm. I'm
wary of this because clang-aarch64-mingw is broken today with no
workaround, and I'm not sure anyone is actively running a GCC
aarch64 MinGW build of Postgres.

I'd lean toward (1) but I'm happy to be guided. If it helps, I can also
narrow the guard to be explicit about the mechanism, e.g. only take the
__builtin_setjmp path when the compiler actually provides it, rather than
keying off arch -- though on x86_64 GCC/clang MinGW that's a
distinction without a difference today. If anyone has an aarch64 GCC
MinGW environment handy, I'd gladly take help confirming both the
compile and the setjmp/longjmp runtime behavior there.

--
nathan

best.

-greg

#4Andrew Dunstan
andrew@dunslane.net
In reply to: Greg Burd (#3)
Re: Don't use __builtin_setjmp on aarch64 MinGW/Windows

On 2026-07-28 Tu 1:46 PM, Greg Burd wrote:

Testing on aarch64/gcc/mingw seems like an important step.

Agreed, and I want to be upfront that I have not been able to test that
combination yet -- I don't currently have an aarch64 GCC MinGW toolchain
(the llvm-mingw / MSYS2 clangarm64 toolchain I build with is clang-based,
which is where the aarch64 buildfarm work has been happening). So the
runtime evidence I offered ("25/25 elog(ERROR)->siglongjmp cycles, nested
PL/pgSQL exceptions, no crash") is specifically for clang-aarch64-mingw,
whose setjmp lowering is its own thing. I should not have implied
anything broader.

My understanding is that there is no such animal on the horizon, that
all the MSYS team's aarch64 efforts are concentrated on clang, which is
why there is no native Strawberry perl for aarch64 (They are too deeply
invested in gcc). What fun, eh?

cheers

andrew

--
Andrew Dunstan
EDB: https://www.enterprisedb.com

#5Greg Burd
greg@burd.me
In reply to: Andrew Dunstan (#4)
Re: Don't use __builtin_setjmp on aarch64 MinGW/Windows

On Tue, Jul 28, 2026, at 5:10 PM, Andrew Dunstan wrote:

On 2026-07-28 Tu 1:46 PM, Greg Burd wrote:

Testing on aarch64/gcc/mingw seems like an important step.

Agreed, and I want to be upfront that I have not been able to test that
combination yet -- I don't currently have an aarch64 GCC MinGW toolchain
(the llvm-mingw / MSYS2 clangarm64 toolchain I build with is clang-based,
which is where the aarch64 buildfarm work has been happening). So the
runtime evidence I offered ("25/25 elog(ERROR)->siglongjmp cycles, nested
PL/pgSQL exceptions, no crash") is specifically for clang-aarch64-mingw,
whose setjmp lowering is its own thing. I should not have implied
anything broader.

My understanding is that there is no such animal on the horizon, that
all the MSYS team's aarch64 efforts are concentrated on clang, which is
why there is no native Strawberry perl for aarch64 (They are too deeply
invested in gcc). What fun, eh?

Hey Andrew, thanks for the info. From what I can find that seems to be the case. So, it's clang with MSYS2 on aarch64 and this patch fixes a small build time issue cleanly.

-greg

Show quoted text

cheers

andrew

--
Andrew Dunstan
EDB: https://www.enterprisedb.com