guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] branch main updated: Fix setjmp/longjmp-related crashes


From: Ludovic Courtès
Subject: [Guile-commits] branch main updated: Fix setjmp/longjmp-related crashes on Windows
Date: Sun, 20 Oct 2024 07:05:33 -0400

This is an automated email from the git hooks/post-receive script.

civodul pushed a commit to branch main
in repository guile.

The following commit(s) were added to refs/heads/main by this push:
     new 08e26836f Fix setjmp/longjmp-related crashes on Windows
08e26836f is described below

commit 08e26836f1116fba4ef1b674f2f9b37e0e4ebb03
Author: Michael Käppler <xmichael-k@web.de>
AuthorDate: Sat Sep 7 22:52:22 2024 +0200

    Fix setjmp/longjmp-related crashes on Windows
    
    * libguile/Makefile.am: add new header file setjump-win.h
    * libguile/continuations.h, libguile/dynstack.c, libguile/dynstack.h,
      libguile/intrinsics.h, libguile/vm.h:
      supply custom `setjmp` macro on Windows
    
    Mingw implements `setjmp (env)` as a macro that expands to
    
     _setjmp (env, faddr)
    
    where `faddr` is set to the current frame address.
    
    This address is then stored as first element in the jump buffer `env`.
    When `longjmp` is called, it tries to unwind the stack up
    to the saved address by calling `RtlUnwindEx` from MSVCRT,
    which will fail, if the stack frames are interwoven with
    JIT-generated code, that violate the Windows x64 calling conventions.
    
    Thus implement the macro ourselves as
    
    _setjmp (env, NULL)
    
    which will toggle a code path in `longjmp` that does no unwinding.
    
    Signed-off-by: Ludovic Courtès <ludo@gnu.org>
---
 libguile/Makefile.am     |  1 +
 libguile/continuations.h |  4 ++++
 libguile/dynstack.c      |  5 +++++
 libguile/dynstack.h      |  5 +++++
 libguile/intrinsics.h    |  4 ++++
 libguile/setjump-win.h   | 17 +++++++++++++++++
 libguile/vm.h            |  4 ++++
 7 files changed, 40 insertions(+)

diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index 59fb5f5fc..5f279a257 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -678,6 +678,7 @@ modinclude_HEADERS =                                \
        rw.h                                    \
        scmsigs.h                               \
        script.h                                \
+       setjump-win.h                           \
        simpos.h                                \
        smob.h                                  \
        snarf.h                                 \
diff --git a/libguile/continuations.h b/libguile/continuations.h
index d83bed9b7..ac636512e 100644
--- a/libguile/continuations.h
+++ b/libguile/continuations.h
@@ -22,7 +22,11 @@
 
 
 
+#ifndef _WIN64
 #include <setjmp.h>
+#else
+#include "libguile/setjump-win.h"
+#endif
 
 #include "libguile/programs.h"
 #include "libguile/throw.h"
diff --git a/libguile/dynstack.c b/libguile/dynstack.c
index 2eec7a7eb..e4ed878c2 100644
--- a/libguile/dynstack.c
+++ b/libguile/dynstack.c
@@ -25,7 +25,12 @@
 #endif
 
 #include <assert.h>
+
+#ifndef _WIN64
 #include <setjmp.h>
+#else
+#include "setjump-win.h"
+#endif
 
 #include "control.h"
 #include "eval.h"
diff --git a/libguile/dynstack.h b/libguile/dynstack.h
index 4c32a0943..6f0775e40 100644
--- a/libguile/dynstack.h
+++ b/libguile/dynstack.h
@@ -22,7 +22,12 @@
 
 
 
+#ifndef _WIN64
 #include <setjmp.h>
+#else
+#include "libguile/setjump-win.h"
+#endif
+
 #include <signal.h>
 
 #include "libguile/scm.h"
diff --git a/libguile/intrinsics.h b/libguile/intrinsics.h
index d2ffc847e..8a1c7c04e 100644
--- a/libguile/intrinsics.h
+++ b/libguile/intrinsics.h
@@ -24,7 +24,11 @@
 #error intrinsics.h is private and uninstalled
 #endif
 
+#ifndef _WIN64
 #include <setjmp.h>
+#else
+#include "libguile/setjump-win.h"
+#endif
 
 #include <libguile/scm.h>
 
diff --git a/libguile/setjump-win.h b/libguile/setjump-win.h
new file mode 100644
index 000000000..bf06e868b
--- /dev/null
+++ b/libguile/setjump-win.h
@@ -0,0 +1,17 @@
+#ifndef _SCM_SETJUMP_WIN_H_
+#define _SCM_SETJUMP_WIN_H_
+
+#include <setjmp.h>
+
+/* On Windows, `setjmp` expands to _setjmp, which takes a second
+   parameter that is set to the current frame address by default.
+   The address is then stored as first element in the jump buffer.
+   When `longjmp` is called, it tries to unwind the stack up
+   to the saved address, which will fail, if the stack frames are
+   interwoven with JIT-generated code.
+   Set the second parameter to NULL to prevent unwinding. */
+#undef setjmp
+#define setjmp(env) _setjmp(env, NULL)
+
+#endif /* _SCM_SETJUMP_WIN_H_ */
+
diff --git a/libguile/vm.h b/libguile/vm.h
index 9681188bd..d5b7138d3 100644
--- a/libguile/vm.h
+++ b/libguile/vm.h
@@ -20,7 +20,11 @@
 #ifndef _SCM_VM_H_
 #define _SCM_VM_H_
 
+#ifndef _WIN64
 #include <setjmp.h>
+#else
+#include "libguile/setjump-win.h"
+#endif
 
 #include <libguile/gc.h>
 #include <libguile/programs.h>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]