Skip to content

Commit

Permalink
Free the alternate signal stack when thread / process stops
Browse files Browse the repository at this point in the history
Commit fc95347 introduced dynamic allocation of the alternate stack
used to process signals.

This commit makes sure the dynamically-allocated stack is freed when
the main OCaml code terminates or an OCaml thread terminates.

In passing, we also reset relevant signal handlers to their default behavior
when the main OCaml code terminates.

Fixes: ocaml#10698
  • Loading branch information
xavierleroy committed Oct 25, 2021
1 parent 4c52549 commit 7803af0
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 3 deletions.
1 change: 1 addition & 0 deletions otherlibs/systhreads/st_stubs.c
Expand Up @@ -550,6 +550,7 @@ static ST_THREAD_FUNCTION caml_thread_start(void * arg)
#ifdef NATIVE_CODE
}
#endif
caml_stop_stack_overflow_detection();
/* The thread now stops running */
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions runtime/caml/signals.h
Expand Up @@ -88,6 +88,7 @@ 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 int caml_setup_stack_overflow_detection(void);
CAMLextern int caml_stop_stack_overflow_detection(void);

CAMLextern void (*caml_enter_blocking_section_hook)(void);
CAMLextern void (*caml_leave_blocking_section_hook)(void);
Expand Down
1 change: 1 addition & 0 deletions runtime/signals_byt.c
Expand Up @@ -82,3 +82,4 @@ int caml_set_signal_action(int signo, int action)
}

CAMLexport int caml_setup_stack_overflow_detection(void) { return 0; }
CAMLexport int caml_stop_stack_overflow_detection(void) { return 0; }
46 changes: 46 additions & 0 deletions runtime/signals_nat.c
Expand Up @@ -288,6 +288,36 @@ void caml_init_signals(void)
#endif
}

/* Termination of signal stuff */

#if defined(TARGET_power) || defined(TARGET_s390x) \
|| 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_power)
set_signal_default(SIGTRAP);
#endif

#if defined(TARGET_s390x)
set_signal_default(SIGFPE);
#endif

#ifdef HAS_STACK_OVERFLOW_DETECTION
set_signal_default(SIGSEGV);
caml_stop_stack_overflow_detection();
#endif
}

/* Allocate and select an alternate stack for handling signals,
especially SIGSEGV signals.
Each thread needs its own alternate stack.
Expand All @@ -308,3 +338,19 @@ CAMLexport int caml_setup_stack_overflow_detection(void)
return 0;
#endif
}

CAMLexport int caml_stop_stack_overflow_detection(void)
{
#ifdef HAS_STACK_OVERFLOW_DETECTION
stack_t oldstk, stk;
stk.ss_flags = SS_DISABLE;
if (sigaltstack(&stk, &oldstk) == -1) return -1;
/* If caml_setup_stack_overflow_detection 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);
return 0;
#else
return 0;
#endif
}
6 changes: 5 additions & 1 deletion runtime/startup_nat.c
Expand Up @@ -92,6 +92,7 @@ void (*caml_termination_hook)(void *) = NULL;

extern value caml_start_program (caml_domain_state*);
extern void caml_init_signals (void);
extern void caml_terminate_signals (void);
#ifdef _WIN32
extern void caml_win32_overflow_detection (void);
#endif
Expand All @@ -106,6 +107,7 @@ extern void caml_install_invalid_parameter_handler();
value caml_startup_common(char_os **argv, int pooling)
{
char_os * exe_name, * proc_self_exe;
value res;
char tos;

/* Initialize the domain */
Expand Down Expand Up @@ -155,7 +157,9 @@ value caml_startup_common(char_os **argv, int pooling)
if (caml_termination_hook != NULL) caml_termination_hook(NULL);
return Val_unit;
}
return caml_start_program(Caml_state);
res = caml_start_program(Caml_state);
caml_terminate_signals();
return res;
}

value caml_startup_exn(char_os **argv)
Expand Down
2 changes: 0 additions & 2 deletions tools/ci/inria/sanitizers/lsan-suppr.txt
@@ -1,4 +1,2 @@
# ocamlyacc doesn't clean memory on exit
leak:ocamlyacc
# Alternate signal stacks are currently never freed (see #10266)
leak:caml_setup_stack_overflow_detection

0 comments on commit 7803af0

Please sign in to comment.