On Tue, 18 Apr 2023, sisyphus wrote:

The mingw-w64 commit that removed use of USE_NO_MINGW_SETJMP_TWO_ARGS
would have affected the former, but I don't see why it would affect the
latter; if the latter works as intended there would be no need for
USE_NO_MINGW_SETJMP_TWO_ARGS in the first place.


Yes - in our 32-bit builds the condition:

#  if defined(USE_NO_MINGW_SETJMP_TWO_ARGS) || (!defined(__BORLANDC__) &&
!defined(__MINGW64__))

will be true even if USE_NO_MINGW_SETJMP_TWO_ARGS is NOT defined.
In that sense, there's no need to define USE_NO_MINGW_SETJMP_TWO_ARGS.

But, wrt the 12.2.0 setjmp.h,  USE_NO_MINGW_SETJMP_TWO_ARGS still needs to
be defined in order to avoid entering the block of code that begins with:

#if !defined(USE_NO_MINGW_SETJMP_TWO_ARGS)

The 13.0.1 setjmp.h has no such block ... though I haven't yet properly
assessed the impact of that absence. (TODO)
Apparently, it's quite ok for MSVC to enter that block.

Well MSVC doesn't have any such ifdefs - a define like USE_NO_MINGW_SETJMP_TWO_ARGS clearly doesn't affect them.

Best thing would be for me to actually test what you have in mind.
What does this reverted setjmp.h exactly look like ? (A patch that I can
apply would suffice.)
Could I then simply test this reverted header by inserting it into my
current gcc-13.0.1 installation, as a replacement for the setjmp.h
originally provided ?
Or does this reversion require that gcc-13.0.1 be rebuilt ? (I'm not set up
to build gcc from source, and would prefer not to.)

There shouldn't be any need to rebuild the toolchain just to try out a modified version of this header.

The 12.2.0 version of setjmp.h caters for a setjmp() function that takes a
single  jmp_buf argument.
It looks to me that the 13.0.1 version of  setjmp.h does not provide that
option.

This is the core of the issue. I'm not sure if I missed these hints at what the issue was before, or if that was just left out so far...

Anyway, I went ahead and tried to build perl myself in the msys2 mingw32 environment, and struck the issue there too. Reverting ead648bf3101bdaa9993958775f5d5f125c0c4de in mingw-w64-headers does fix the issue. I guess we could do that, but for Perl, it doesn't feel like the right way forward anyway.

Looking at the perl code, the issue seems to be that XSUB.h undefs setjmp and tries to redirect it to PerlProc_setjmp, which in the end expands back to just setjmp. And by doing this, it loses the system header's original definition of setjmp, which is an toolchain implementaton detail that is subject to change. The various hacks in threads.xs have essentially tried to reimplement what the system setjmp.h header did, in a brittle way.

The most robust way forward would, IMO, be to just stop trying to redefine it, and stop undeffing/overriding the system's setjmp() function, since that's what it is going to be using in the end anyway.

See the attached patch, that does seem to work for me at least, tested in an msys2/mingw32 environment. If you've got MSVC build environments for Perl, please do try it out there as well, I believe it should work the same there.

If the attached patch doesn't make it through the mailing list, try grabbing https://martin.st/temp/0001-Remove-Windows-setjmp-redefinition-hacks.patch instead.

// Martin
From d6e40fd518fe9e1317a8d3b81d387d098c162d53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <[email protected]>
Date: Tue, 18 Apr 2023 11:03:41 +0300
Subject: [PATCH] Remove Windows setjmp redefinition hacks

Within Perl, the main PerlProc_setjmp symbol, in iperlsys.h, redirects to
Sigsetjmp in iperlsys.h, and on Windows, Sigsetjmp redirects to setjmp.
This layering works fine everywhere it is used.

However, the header XSUB.h, which seems to be meant to intercept direct
calls to system functions and redirect them to the corresponding
PerlProc names, breaks setjmp on Windows. Previously, XSUB.h would
undef setjmp and redirect it to PerlProc_setjmp, but this breaks
the regular PerlProc_setjmp -> Sigsetjmp -> setjmp expansion, since
setjmp isn't a regular function but a macro on Windows, and exactly
what it expands to is implementation defined.

This has been worked around since 2006 (since
4dcb9e53db5ab3b8d2b2f8eaba341cb2c0c5d2b8) in threads.xs by undeffing
XSUB.h's setjmp define, and redefining it to what setjmp.h would
do in e.g. MSVC headers.

For MSVC headers, this has been mostly straightforward, but on
mingw platforms, setjmp can expand to various different things;
trying to replicate the system headers in threads.xs is brittle,
as this has required numerous minor patches on mingw-w64 through
the years. This replication recently broke on mingw-w64 on i386,
when support for USE_NO_MINGW_SETJMP_TWO_ARGS was removed.

Instead of trying to mimic the system's setjmp definition, just
stop overriding the system header's setjmp/longjmp and keep them
intact.
---
 XSUB.h                  | 14 ++++++++++++++
 dist/threads/threads.xs | 17 -----------------
 2 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/XSUB.h b/XSUB.h
index 82cd0dc777..b7f92abc5f 100644
--- a/XSUB.h
+++ b/XSUB.h
@@ -504,7 +504,14 @@ Rethrows a previously caught exception.  See L<perlguts/"Exception Handling">.
 #    undef fgetpos
 #    undef ioctl
 #    undef getlogin
+
+/* Don't undefine/redefine setjmp on Windows; PerlProc_setjmp gets redirected
+ * back to plain setjmp in the end, but then we've lost the system header's
+ * definition of it. Just keep the system headers versions of setjmp intact. */
+#ifndef _WIN32
 #    undef setjmp
+#endif
+
 #    undef getc
 #    undef ungetc
 #    undef fileno
@@ -609,8 +616,15 @@ Rethrows a previously caught exception.  See L<perlguts/"Exception Handling">.
 #    define sleep		PerlProc_sleep
 #    define times		PerlProc_times
 #    define wait		PerlProc_wait
+
+/* Don't undefine/redefine setjmp on Windows; PerlProc_setjmp gets redirected
+ * back to plain setjmp in the end, but then we've lost the system header's
+ * definition of it. Just keep the system headers versions of setjmp intact. */
+#ifndef _WIN32
 #    define setjmp		PerlProc_setjmp
 #    define longjmp		PerlProc_longjmp
+#endif
+
 #    define signal		PerlProc_signal
 #    define getpid		PerlProc_getpid
 #    define gettimeofday	PerlProc_gettimeofday
diff --git a/dist/threads/threads.xs b/dist/threads/threads.xs
index 25fec167aa..1a403af2f6 100644
--- a/dist/threads/threads.xs
+++ b/dist/threads/threads.xs
@@ -1,24 +1,7 @@
 #define PERL_NO_GET_CONTEXT
-/* Workaround for mingw 32-bit compiler by mingw-w64.sf.net - has to come before any #include.
- * It also defines USE_NO_MINGW_SETJMP_TWO_ARGS for the mingw.org 32-bit compilers ... but
- * that's ok as that compiler makes no use of that symbol anyway */
-#if defined(WIN32) && defined(__MINGW32__) && !defined(__MINGW64__)
-#  define USE_NO_MINGW_SETJMP_TWO_ARGS 1
-#endif
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
-/* Workaround for XSUB.h bug under WIN32 */
-#ifdef WIN32
-#  undef setjmp
-#  if defined(USE_NO_MINGW_SETJMP_TWO_ARGS) || (!defined(__BORLANDC__) && !defined(__MINGW64__))
-#    define setjmp(x) _setjmp(x)
-#  endif
-#  if defined(__MINGW64__)
-#    include <intrin.h>
-#    define setjmp(x) _setjmpex((x), mingw_getsp())
-#  endif
-#endif
 #define NEED_PL_signals
 #define NEED_sv_2pv_flags
 #include "ppport.h"
-- 
2.34.1

_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to