From 627128baa637841b12ed87579a4c2e4311635505 Mon Sep 17 00:00:00 2001 From: rtoy <rtoy> Date: Fri, 24 Dec 2004 15:11:10 +0000 Subject: [PATCH] From Helmut Eller, cmucl-imp, 2004-10-05: on Linux/x86, the Lisp signal handler for SIGSEGV overwrites the beginning of the control stack. For SIGSEGV we use an extra signal stack and when the signal isn't handled by the GC or by the stack overflow handler we call eventually call_into_lisp. call_into_lisp tests whether the current stack pointer points to the normal control stack. But the test fails because we use the extra signal stack, so call_into_lisp just sets the stack pointer to the beginning of the normal control stack. This is not much fun for debugging because the backtrace is truncated and it's also no longer possible to throw to the top-level-catcher because its frame was overwritten. I tried to fix that with the patch below. The idea is to switch back to the normal stack before calling the Lisp handler. The patch may not be very elegant but it is at least short :) . --- lisp/Linux-os.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lisp/Linux-os.c b/lisp/Linux-os.c index 514e103aa..c582a8cb3 100644 --- a/lisp/Linux-os.c +++ b/lisp/Linux-os.c @@ -15,7 +15,7 @@ * GENCGC support by Douglas Crosher, 1996, 1997. * Alpha support by Julian Dolby, 1999. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Linux-os.c,v 1.22 2004/10/19 19:12:03 cwang Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Linux-os.c,v 1.23 2004/12/24 15:11:10 rtoy Exp $ * */ @@ -45,6 +45,7 @@ #include <link.h> #include <dlfcn.h> #include <fpu_control.h> +#include <assert.h> #include "validate.h" size_t os_vm_page_size; @@ -246,6 +247,15 @@ static void sigsegv_handle_now(HANDLER_ARGS) interrupt_handle_now(signal, contextstruct); } +static int tramp_signal; +static struct sigcontext tramp_contextstruct; + +static void sigsegv_handler_tramp (void) +{ + sigsegv_handle_now (tramp_signal, tramp_contextstruct); + assert (0); +} + void sigsegv_handler(HANDLER_ARGS) { GET_CONTEXT @@ -281,6 +291,19 @@ void sigsegv_handler(HANDLER_ARGS) #else DPRINTF(0,(stderr,"sigsegv: eip: %lx\n",context->eip)); #endif + +#ifdef RED_ZONE_HIT + { + /* Switch back to the normal stack and invoke the Lisp signal + handler there. Global variables are used to pass the context + to the other stack. */ + tramp_signal = signal; + tramp_contextstruct = contextstruct; + SC_PC(context) = sigsegv_handler_tramp; + return; + } +#endif + sigsegv_handle_now(signal, contextstruct); } #else -- GitLab