Skip to content

Commit

Permalink
Dynamically allocate the alternate signal stack (ocaml#10266)
Browse files Browse the repository at this point in the history
In Glibc 2.34 and later, SIGSTKSZ may not be a compile-time constant.
It is no longer possible to statically allocate the alternate signal
stack for the main thread, as we've been doing for the last 25 years.

This commit implements dynamic allocation of the alternate signal stack
even for the main thread.  It reuses the code already in place to allocate
the alternate signal stack for other threads.

Fixes: ocaml#10250.
  • Loading branch information
xavierleroy authored and dra27 committed Oct 25, 2021
1 parent 9844919 commit 83bd2f5
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 13 deletions.
2 changes: 1 addition & 1 deletion runtime/caml/signals.h
Expand Up @@ -87,7 +87,7 @@ value caml_do_pending_actions_exn (void);
value caml_process_pending_actions_with_root (value extra_root); // raises
value caml_process_pending_actions_with_root_exn (value extra_root);
int caml_set_signal_action(int signo, int action);
CAMLextern void caml_setup_stack_overflow_detection(void);
CAMLextern int caml_setup_stack_overflow_detection(void);

CAMLextern void (*caml_enter_blocking_section_hook)(void);
CAMLextern void (*caml_leave_blocking_section_hook)(void);
Expand Down
2 changes: 1 addition & 1 deletion runtime/signals_byt.c
Expand Up @@ -81,4 +81,4 @@ int caml_set_signal_action(int signo, int action)
return 0;
}

CAMLexport void caml_setup_stack_overflow_detection(void) {}
CAMLexport int caml_setup_stack_overflow_detection(void) { return 0; }
25 changes: 14 additions & 11 deletions runtime/signals_nat.c
Expand Up @@ -181,8 +181,6 @@ DECLARE_SIGNAL_HANDLER(trap_handler)
#error "CONTEXT_SP is required if HAS_STACK_OVERFLOW_DETECTION is defined"
#endif

static char sig_alt_stack[SIGSTKSZ];

/* Code compiled with ocamlopt never accesses more than
EXTRA_STACK bytes below the stack pointer. */
#define EXTRA_STACK 256
Expand Down Expand Up @@ -276,28 +274,33 @@ void caml_init_signals(void)
#endif

#ifdef HAS_STACK_OVERFLOW_DETECTION
{
stack_t stk;
if (caml_setup_stack_overflow_detection() != -1) {
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);
if (sigaltstack(&stk, NULL) == 0) { sigaction(SIGSEGV, &act, NULL); }
sigaction(SIGSEGV, &act, NULL);
}
#endif
}

CAMLexport void caml_setup_stack_overflow_detection(void)
/* Allocate and select an alternate stack for handling signals,
especially SIGSEGV signals.
Each thread needs its own alternate stack.
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 (issue #10250). */

CAMLexport int caml_setup_stack_overflow_detection(void)
{
#ifdef HAS_STACK_OVERFLOW_DETECTION
stack_t stk;
stk.ss_sp = malloc(SIGSTKSZ);
if (stk.ss_sp == NULL) return -1;
stk.ss_size = SIGSTKSZ;
stk.ss_flags = 0;
if (stk.ss_sp)
sigaltstack(&stk, NULL);
return sigaltstack(&stk, NULL);
#else
return 0;
#endif
}

0 comments on commit 83bd2f5

Please sign in to comment.