diff --git a/src/c/main.d b/src/c/main.d index d49528b72..816646ffa 100644 --- a/src/c/main.d +++ b/src/c/main.d @@ -175,6 +175,7 @@ ecl_init_env(cl_env_ptr env) env->packages_to_be_created = Cnil; env->packages_to_be_created_p = Cnil; + env->fault_address = env; } void diff --git a/src/c/unixint.d b/src/c/unixint.d index 8885ed477..74440fdf0 100644 --- a/src/c/unixint.d +++ b/src/c/unixint.d @@ -571,14 +571,12 @@ handler_fn_protype(sigsegv_handler, int sig, siginfo_t *info, void *aux) "\n;;;\n;;; Stack overflow.\n" ";;; Jumping to the outermost toplevel prompt\n" ";;;\n\n"; -#ifndef HAVE_SIGPROCMASK static const char *segv_msg = "\n;;;\n" ";;; Detected access to protected memory, " "also kwown as 'segmentation fault'.\n" ";;; Jumping to the outermost toplevel prompt\n" ";;;\n\n"; -#endif cl_env_ptr the_env; reinstall_signal(sig, sigsegv_handler); if (!ecl_option_values[ECL_OPT_BOOTED]) { @@ -622,16 +620,16 @@ handler_fn_protype(sigsegv_handler, int sig, siginfo_t *info, void *aux) return; } # endif -# if 0 && defined(SA_ONSTACK) - /* The handler is executed in an externally allocated stack, and - * thus it is not safe to execute lisp code here. We just bounce - * up to the outermost toplevel. - */ - unblock_signal(the_env, SIGSEGV); - ecl_unrecoverable_error(the_env, segv_msg); -# else - handle_or_queue(the_env, @'ext::segmentation-violation', SIGSEGV); -# endif + /* Do not attempt an error handler if we nest two serious + * errors in the same thread */ + if (the_env->fault_address == info->si_addr) { + the_env->fault_address = info->si_addr; + unblock_signal(the_env, SIGSEGV); + ecl_unrecoverable_error(the_env, segv_msg); + } else { + the_env->fault_address = info->si_addr; + handle_or_queue(the_env, @'ext::segmentation-violation', SIGSEGV); + } #else /* * We cannot distinguish between a stack overflow and a simple @@ -647,13 +645,20 @@ handler_fn_protype(sigsegv_handler, int sig, siginfo_t *info, void *aux) static void handler_fn_protype(sigbus_handler, int sig, siginfo_t *info, void *aux) { + static const char *sigbus_msg = + "\n;;;\n" + ";;; Detected access to invalid or protected memory, " + "also kwown as 'SIGBUS'.\n" + ";;; Jumping to the outermost toplevel prompt\n" + ";;;\n\n"; cl_env_ptr the_env; reinstall_signal(sig, sigsegv_handler); /* The lisp environment might not be installed. */ the_env = ecl_process_env(); if (zombie_process(the_env)) return; -#if defined(SA_SIGINFO) && defined(ECL_USE_MPROTECT) +#if defined(SA_SIGINFO) +# if defined(ECL_USE_MPROTECT) /* We access the environment when it was protected. That * means there was a pending signal. */ if (((char*)the_env <= (char*)info->si_addr) && @@ -669,8 +674,20 @@ handler_fn_protype(sigbus_handler, int sig, siginfo_t *info, void *aux) } return; } -#endif - handle_or_queue(the_env, @'ext::segmentation-violation', SIGBUS); +# endif /* ECL_USE_MPROTECT */ + /* Do not attempt an error handler if we nest two serious + * errors in the same thread */ + if (the_env->fault_address == info->si_addr) { + the_env->fault_address = info->si_addr; + unblock_signal(the_env, SIGBUS); + ecl_unrecoverable_error(the_env, sigbus_msg); + } else { + the_env->fault_address = info->si_addr; + handle_or_queue(the_env, @'ext::segmentation-violation', SIGSEGV); + } +#endif /* SA_SIGINFO */ + unblock_signal(the_env, SIGBUS); + ecl_unrecoverable_error(the_env, sigbus_msg); } #endif diff --git a/src/h/external.h b/src/h/external.h index 1f5947fa7..480383aad 100755 --- a/src/h/external.h +++ b/src/h/external.h @@ -134,6 +134,9 @@ struct cl_env_struct { * to be explicitely created by the compiled code itself. */ cl_object packages_to_be_created; cl_object packages_to_be_created_p; + + /* Segmentation fault address */ + void *fault_address; }; #ifndef __GNUC__ @@ -1758,6 +1761,7 @@ extern ECL_API cl_object mp_mailbox_send(cl_object mailbox, cl_object msg); extern ECL_API cl_object ecl_atomic_get(cl_object *slot); extern ECL_API void ecl_atomic_push(cl_object *slot, cl_object o); +extern ECL_API void ecl_atomic_nconc(cl_object l, cl_object *slot); extern ECL_API cl_object ecl_atomic_pop(cl_object *slot); extern ECL_API cl_index ecl_atomic_index_incf(cl_index *slot);