summaryrefslogtreecommitdiff
path: root/asmrun
diff options
context:
space:
mode:
Diffstat (limited to 'asmrun')
-rw-r--r--asmrun/fail.c7
-rw-r--r--asmrun/signals_asm.c69
-rw-r--r--asmrun/startup.c7
3 files changed, 72 insertions, 11 deletions
diff --git a/asmrun/fail.c b/asmrun/fail.c
index d73cb88524..2f06432018 100644
--- a/asmrun/fail.c
+++ b/asmrun/fail.c
@@ -31,6 +31,8 @@
#include "caml/roots.h"
#include "caml/callback.h"
+extern void caml_terminate_signals(void);
+
/* The globals holding predefined exceptions */
typedef value caml_generated_constant[1];
@@ -60,7 +62,10 @@ char * caml_exception_pointer = NULL;
void caml_raise(value v)
{
Unlock_exn();
- if (caml_exception_pointer == NULL) caml_fatal_uncaught_exception(v);
+ if (caml_exception_pointer == NULL) {
+ caml_terminate_signals();
+ caml_fatal_uncaught_exception(v);
+ }
#ifndef Stack_grows_upwards
#define PUSHED_AFTER <
diff --git a/asmrun/signals_asm.c b/asmrun/signals_asm.c
index f124a07674..b4e2516ae1 100644
--- a/asmrun/signals_asm.c
+++ b/asmrun/signals_asm.c
@@ -194,7 +194,6 @@ DECLARE_SIGNAL_HANDLER(trap_handler)
#ifdef HAS_STACK_OVERFLOW_DETECTION
static char * system_stack_top;
-static char sig_alt_stack[SIGSTKSZ];
#if defined(SYS_linux)
/* PR#4746: recent Linux kernels with support for stack randomization
@@ -295,17 +294,69 @@ void caml_init_signals(void)
{
stack_t stk;
struct sigaction act;
- stk.ss_sp = sig_alt_stack;
- stk.ss_size = SIGSTKSZ;
- stk.ss_flags = 0;
- SET_SIGACT(act, segv_handler);
- act.sa_flags |= SA_ONSTACK | SA_NODEFER;
- sigemptyset(&act.sa_mask);
- system_stack_top = (char *) &act;
- if (sigaltstack(&stk, NULL) == 0) { sigaction(SIGSEGV, &act, NULL); }
+ /* Allocate and select an alternate stack for handling signals,
+ especially SIGSEGV signals.
+ The alternate stack used to be statically-allocated for the main thread,
+ but this is incompatible with Glibc 2.34 and newer, where SIGSTKSZ
+ may not be a compile-time constant. */
+ stk.ss_sp = malloc(SIGSTKSZ);
+ if (stk.ss_sp != NULL) {
+ stk.ss_size = SIGSTKSZ;
+ stk.ss_flags = 0;
+ SET_SIGACT(act, segv_handler);
+ act.sa_flags |= SA_ONSTACK | SA_NODEFER;
+ sigemptyset(&act.sa_mask);
+ system_stack_top = (char *) &act;
+ if (sigaltstack(&stk, NULL) == 0)
+ sigaction(SIGSEGV, &act, NULL);
+ else
+ free(stk.ss_sp);
+ }
}
#endif
#if defined(_WIN32) && !defined(_WIN64)
caml_win32_overflow_detection();
#endif
}
+
+/* Termination of signal stuff */
+
+#if defined(TARGET_power) || defined(TARGET_s390x) \
+ || defined(TARGET_sparc) && defined(SYS_solaris) \
+ || defined(HAS_STACK_OVERFLOW_DETECTION)
+static void set_signal_default(int signum)
+{
+ struct sigaction act;
+ sigemptyset(&act.sa_mask);
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigaction(signum, &act, NULL);
+}
+#endif
+
+void caml_terminate_signals(void)
+{
+#if defined(TARGET_sparc) && defined(SYS_solaris)
+ set_signal_default(SIGILL);
+#endif
+
+#if defined(TARGET_power)
+ set_signal_default(SIGTRAP);
+#endif
+
+#if defined(TARGET_s390x)
+ set_signal_default(SIGFPE);
+#endif
+
+#ifdef HAS_STACK_OVERFLOW_DETECTION
+ set_signal_default(SIGSEGV);
+ stack_t oldstk, stk;
+ stk.ss_flags = SS_DISABLE;
+ if (sigaltstack(&stk, &oldstk) == 0) {
+ /* If caml_init_signals failed, we are not using an alternate signal stack.
+ SS_DISABLE will be set in oldstk, and there is nothing to free in this
+ case. */
+ if (! (oldstk.ss_flags & SS_DISABLE)) free(oldstk.ss_sp);
+ }
+#endif
+}
diff --git a/asmrun/startup.c b/asmrun/startup.c
index 70bbc4369d..a1cb06a7d1 100644
--- a/asmrun/startup.c
+++ b/asmrun/startup.c
@@ -92,6 +92,7 @@ void (*caml_termination_hook)(void *) = NULL;
extern value caml_start_program (void);
extern void caml_init_ieee_floats (void);
extern void caml_init_signals (void);
+extern void caml_terminate_signals(void);
#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
@@ -103,6 +104,7 @@ extern void caml_install_invalid_parameter_handler();
value caml_startup_exn(char **argv)
{
char * exe_name, * proc_self_exe;
+ value res;
char tos;
#ifdef WITH_SPACETIME
@@ -138,10 +140,13 @@ value caml_startup_exn(char **argv)
exe_name = caml_search_exe_in_path(exe_name);
caml_sys_init(exe_name, argv);
if (sigsetjmp(caml_termination_jmpbuf.buf, 0)) {
+ caml_terminate_signals();
if (caml_termination_hook != NULL) caml_termination_hook(NULL);
return Val_unit;
}
- return caml_start_program();
+ res = caml_start_program();
+ caml_terminate_signals();
+ return res;
}
void caml_startup(char **argv)