gc: fix signal handlers for generational garbage collector

The boehm gc needs SIGSEGV or SIGBUS to track dirty pages (see
GC_write_fault_handler). Thus these signals need to be unblocked at
all times.
This commit is contained in:
Marius Gerbershagen 2020-03-28 17:09:21 +01:00
parent f7f0edebd6
commit 73af5cdcdd
3 changed files with 16 additions and 4 deletions

View file

@ -592,14 +592,16 @@ mp_process_enable(cl_object process)
pthread_attr_init(&pthreadattr);
pthread_attr_setdetachstate(&pthreadattr, PTHREAD_CREATE_DETACHED);
/*
* We launch the thread with the signal mask specified in cl_core.
* The reason is that we might need to block certain signals
* to be processed by the signal handling thread in unixint.d
* Block all asynchronous signals until the thread is completely
* set up. The synchronous signals SIGSEGV and SIGBUS are needed
* by the gc and thus can't be blocked.
*/
#ifdef HAVE_SIGPROCMASK
{
sigset_t new, previous;
sigfillset(&new);
sigdelset(&new, SIGSEGV);
sigdelset(&new, SIGBUS);
pthread_sigmask(SIG_BLOCK, &new, &previous);
code = pthread_create(&process->process.thread, &pthreadattr,
thread_entry_point, process);
@ -764,6 +766,10 @@ mp_block_signals(void)
cl_object previous = mp_get_sigmask();
sigset_t all_signals;
sigfillset(&all_signals);
/* SIGSEGV or SIGBUS are needed by the gc in incremental mode and
* can thus never be blocked */
sigdelset(&all_signals, SIGSEGV);
sigdelset(&all_signals, SIGBUS);
if (pthread_sigmask(SIG_SETMASK, &all_signals, NULL))
FElibc_error("MP:BLOCK-SIGNALS failed in a call to pthread_sigmask",0);
@(return previous);

View file

@ -580,7 +580,9 @@ asynchronous_signal_servicing_thread()
const cl_env_ptr the_env = ecl_process_env();
int interrupt_signal = -1;
/*
* We block all signals except the usual interrupt thread and GC signals.
* We block all signals except the usual interrupt thread and
* GC signals (including SIGSEGV and SIGSEGV which are needed
* when the GC runs in incremental mode).
*/
{
sigset_t handled_set;
@ -591,6 +593,8 @@ asynchronous_signal_servicing_thread()
sigdelset(&handled_set, interrupt_signal);
sigdelset(&handled_set, GC_get_suspend_signal());
sigdelset(&handled_set, GC_get_thr_restart_signal());
sigdelset(&handled_set, SIGSEGV);
sigdelset(&handled_set, SIGBUS);
}
pthread_sigmask(SIG_BLOCK, &handled_set, NULL);
}

View file

@ -29,6 +29,8 @@
# define ECL_STACK_RESIZE_DISABLE_INTERRUPTS(the_env) \
sigset_t __sigset_new, __sigset_previous; \
sigfillset(&__sigset_new); \
sigdelset(&__sigset_new, SIGSEGV); \
sigdelset(&__sigset_new, SIGBUS); \
pthread_sigmask(SIG_BLOCK, &__sigset_new, &__sigset_previous)
# define ECL_STACK_RESIZE_ENABLE_INTERRUPTS(the_env) \
pthread_sigmask(SIG_SETMASK, &__sigset_previous, NULL)