From: Gabor M. <me...@us...> - 2009-02-16 22:13:03
|
Update of /cvsroot/sbcl/sbcl/src/runtime In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv17987/src/runtime Modified Files: interrupt.c interrupt.h x86-64-darwin-os.c x86-darwin-os.c Log Message: 1.0.25.36: unblock signals on low level errors Low level errors (control stack exhausted, memory fault) may trigger at inconvenient times such as in signal handlers still running with deferrables blocked. Due to the condition handling mechanism this leads to executing user code at unsafe places and the image may very well become corrupted. To allow continuing anyway with fingers crossed to diagnose the problem, deferrable and/or gc signals are unblocked before arranging for returning to the Lisp function that signals the appropriate condition. Before that is done, however, a warning is fprintf'ed to stderr to that this important piece of information is not lost in some generic condition handler (or in a interrupt handler async unwinding before anyone gets a chance to handle the condition) which makes diagnosis of subsequent problems very hard. This was brought to light by the checks added in the previous commit. Index: interrupt.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/interrupt.c,v retrieving revision 1.157 retrieving revision 1.158 diff -u -d -r1.157 -r1.158 --- interrupt.c 16 Feb 2009 21:54:06 -0000 1.157 +++ interrupt.c 16 Feb 2009 21:56:20 -0000 1.158 @@ -111,6 +111,31 @@ } void +sigdelset_deferrable(sigset_t *s) +{ + sigdelset(s, SIGHUP); + sigdelset(s, SIGINT); + sigdelset(s, SIGQUIT); + sigdelset(s, SIGPIPE); + sigdelset(s, SIGALRM); + sigdelset(s, SIGURG); + sigdelset(s, SIGTSTP); + sigdelset(s, SIGCHLD); + sigdelset(s, SIGIO); +#ifndef LISP_FEATURE_HPUX + sigdelset(s, SIGXCPU); + sigdelset(s, SIGXFSZ); +#endif + sigdelset(s, SIGVTALRM); + sigdelset(s, SIGPROF); + sigdelset(s, SIGWINCH); + +#ifdef LISP_FEATURE_SB_THREAD + sigdelset(s, SIG_INTERRUPT_THREAD); +#endif +} + +void sigaddset_blockable(sigset_t *sigset) { sigaddset_deferrable(sigset); @@ -125,6 +150,14 @@ #endif } +void +sigdelset_gc(sigset_t *sigset) +{ +#ifdef LISP_FEATURE_SB_THREAD + sigdelset(sigset,SIG_STOP_FOR_GC); +#endif +} + /* initialized in interrupt_init */ sigset_t deferrable_sigset; sigset_t blockable_sigset; @@ -310,9 +343,23 @@ } void +unblock_deferrable_signals_in_sigset(sigset_t *sigset) +{ +#ifndef LISP_FEATURE_WIN32 + if (interrupt_handler_pending_p()) + lose("unblock_deferrable_signals_in_sigset: losing proposition\n"); + check_gc_signals_unblocked_in_sigset_or_lose(sigset); + sigdelset_deferrable(sigset); +#endif +} + +void unblock_deferrable_signals(void) { #ifndef LISP_FEATURE_WIN32 + if (interrupt_handler_pending_p()) + lose("unblock_deferrable_signals: losing proposition\n"); + check_gc_signals_unblocked_or_lose(); thread_sigmask(SIG_UNBLOCK, &deferrable_sigset, 0); #endif } @@ -325,6 +372,30 @@ #endif } +void +unblock_signals_in_context_and_maybe_warn(os_context_t *context) +{ +#ifndef LISP_FEATURE_WIN32 + int i, oops=0; + sigset_t *sigset=os_context_sigmask_addr(context); + for(i = 1; i < NSIG; i++) { + if (sigismember(&gc_sigset, i) && sigismember(sigset, i)) { + if (!oops) { + fprintf(stderr, +"Enabling blocked gc signals to allow returning to Lisp without risking\n\ +gc deadlocks. Since GC signals are only blocked in signal handlers when \n\ +they are not safe to interrupt at all, this is a pretty severe occurrence.\n"); + } + oops=1; + } + } + sigdelset_gc(sigset); + if (!interrupt_handler_pending_p()) { + unblock_deferrable_signals_in_sigset(sigset); + } +#endif +} + /* * utility routines used by various signal handlers @@ -1180,6 +1251,11 @@ protect_control_stack_guard_page(0); protect_control_stack_return_guard_page(1); +#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK + /* For the unfortunate case, when the control stack is + * exhausted in a signal handler. */ + unblock_signals_in_context_and_maybe_warn(context); +#endif arrange_return_to_lisp_function (context, StaticSymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)); return 1; @@ -1190,6 +1266,7 @@ * unprotect this one. This works even if we somehow missed * the return-guard-page, and hit it on our way to new * exhaustion instead. */ + fprintf(stderr, "INFO: Control stack guard page reprotected\n"); protect_control_stack_guard_page(1); protect_control_stack_return_guard_page(0); return 1; @@ -1444,6 +1521,7 @@ current_memory_fault_address = addr; /* To allow debugging memory faults in signal handlers and such. */ corruption_warning_and_maybe_lose("Memory fault"); + unblock_signals_in_context_and_maybe_warn(context); arrange_return_to_lisp_function(context, StaticSymbolFunction(MEMORY_FAULT_ERROR)); } Index: interrupt.h =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/interrupt.h,v retrieving revision 1.40 retrieving revision 1.41 diff -u -d -r1.40 -r1.41 --- interrupt.h 16 Feb 2009 21:53:25 -0000 1.40 +++ interrupt.h 16 Feb 2009 21:56:20 -0000 1.41 @@ -40,6 +40,7 @@ extern void block_blockable_signals(void); extern void unblock_deferrable_signals(void); extern void unblock_gc_signals(void); +extern void unblock_signals_in_context_and_maybe_warn(os_context_t *context); extern void check_deferrables_blocked_or_lose(void); extern void check_blockables_blocked_or_lose(void); Index: x86-64-darwin-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-64-darwin-os.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- x86-64-darwin-os.c 9 Oct 2008 00:36:09 -0000 1.6 +++ x86-64-darwin-os.c 16 Feb 2009 21:56:20 -0000 1.7 @@ -280,6 +280,7 @@ control_stack_exhausted_handler(int signal, siginfo_t *siginfo, void *void_context) { os_context_t *context = arch_os_get_context(&void_context); + unblock_signals_in_context_and_maybe_warn(context); arrange_return_to_lisp_function (context, StaticSymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)); } Index: x86-darwin-os.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-darwin-os.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- x86-darwin-os.c 9 Oct 2008 00:36:09 -0000 1.13 +++ x86-darwin-os.c 16 Feb 2009 21:56:20 -0000 1.14 @@ -374,6 +374,7 @@ control_stack_exhausted_handler(int signal, siginfo_t *siginfo, void *void_context) { os_context_t *context = arch_os_get_context(&void_context); + unblock_signals_in_context_and_maybe_warn(context); arrange_return_to_lisp_function (context, StaticSymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)); } |