From: Gabor M. <me...@us...> - 2009-05-11 13:24:42
|
Update of /cvsroot/sbcl/sbcl/src/runtime In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv25495/src/runtime Modified Files: interrupt.c monitor.c thread.c thread.h Log Message: 1.0.28.37: resignal signals received in foreign threads Signals delivered to threads started from foreign land (read: directly by pthread_create, not by MAKE-THREAD) are redirected to a Lisp thread by blocking all signals and resignalling. Index: interrupt.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/interrupt.c,v retrieving revision 1.174 retrieving revision 1.175 diff -u -d -r1.174 -r1.175 --- interrupt.c 8 Apr 2009 16:04:04 -0000 1.174 +++ interrupt.c 11 May 2009 13:24:34 -0000 1.175 @@ -68,6 +68,19 @@ #include "genesis/simple-fun.h" #include "genesis/cons.h" +/* When we catch an internal error, should we pass it back to Lisp to + * be handled in a high-level way? (Early in cold init, the answer is + * 'no', because Lisp is still too brain-dead to handle anything. + * After sufficient initialization has been completed, the answer + * becomes 'yes'.) */ +boolean internal_errors_enabled = 0; + +#ifndef LISP_FEATURE_WIN32 +static +void (*interrupt_low_level_handlers[NSIG]) (int, siginfo_t*, os_context_t*); +#endif +union interrupt_handler interrupt_handlers[NSIG]; + /* Under Linux on some architectures, we appear to have to restore the * FPU control word from the context, as after the signal is delivered * we appear to have a null FPU control word. */ @@ -80,6 +93,54 @@ os_context_t *context = arch_os_get_context(&void_context); #endif +/* Foreign code may want to start some threads on its own. + * Non-targetted, truly asynchronous signals can be delivered to + * basically any thread, but invoking Lisp handlers in such foregign + * threads is really bad, so let's resignal it. + * + * This should at least bring attention to the problem, but it cannot + * work for SIGSEGV and similar. It is good enough for timers, and + * maybe all deferrables. */ + +static void +add_handled_signals(sigset_t *sigset) +{ + int i; + for(i = 1; i < NSIG; i++) { + if (!(ARE_SAME_HANDLER(interrupt_low_level_handlers[i], SIG_DFL)) || + !(ARE_SAME_HANDLER(interrupt_handlers[i].c, SIG_DFL))) { + sigaddset(sigset, i); + } + } +} + +void block_signals(sigset_t *what, sigset_t *where, sigset_t *old); + +static boolean +maybe_resignal_to_lisp_thread(int signal, os_context_t *context) +{ +#ifdef LISP_FEATURE_SB_THREAD + if (!pthread_getspecific(lisp_thread)) { + if (!(sigismember(&deferrable_sigset,signal))) { + corruption_warning_and_maybe_lose + ("Received signal %d in non-lisp thread %lu, resignalling to a lisp thread.", + signal, + pthread_self()); + } + { + sigset_t sigset; + sigemptyset(&sigset); + add_handled_signals(&sigset); + block_signals(&sigset, 0, 0); + block_signals(&sigset, os_context_sigmask_addr(context), 0); + kill(getpid(), signal); + } + return 1; + } else +#endif + return 0; +} + /* These are to be used in signal handlers. Currently all handlers are * called from one of: * @@ -98,10 +159,11 @@ * kernel properly, so we fix it up ourselves in the * arch_os_get_context(..) function. -- CSR, 2002-07-23 */ -#define SAVE_ERRNO(context,void_context) \ +#define SAVE_ERRNO(signal,context,void_context) \ { \ int _saved_errno = errno; \ RESTORE_FP_CONTROL_WORD(context,void_context); \ + if (!maybe_resignal_to_lisp_thread(signal, context)) \ { #define RESTORE_ERRNO \ @@ -531,20 +593,6 @@ } #endif } - -/* When we catch an internal error, should we pass it back to Lisp to - * be handled in a high-level way? (Early in cold init, the answer is - * 'no', because Lisp is still too brain-dead to handle anything. - * After sufficient initialization has been completed, the answer - * becomes 'yes'.) */ -boolean internal_errors_enabled = 0; - -#ifndef LISP_FEATURE_WIN32 -static -void (*interrupt_low_level_handlers[NSIG]) (int, siginfo_t*, os_context_t*); -#endif -union interrupt_handler interrupt_handlers[NSIG]; - /* * utility routines used by various signal handlers @@ -1100,10 +1148,9 @@ static void maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(context,void_context); + SAVE_ERRNO(signal,context,void_context); struct thread *thread = arch_os_get_current_thread(); struct interrupt_data *data = thread->interrupt_data; - if(!maybe_defer_handler(interrupt_handle_now,data,signal,info,context)) interrupt_handle_now(signal, info, context); RESTORE_ERRNO; @@ -1123,7 +1170,7 @@ static void low_level_maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(context,void_context); + SAVE_ERRNO(signal,context,void_context); struct thread *thread = arch_os_get_current_thread(); struct interrupt_data *data = thread->interrupt_data; @@ -1209,7 +1256,7 @@ void interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(context,void_context); + SAVE_ERRNO(signal,context,void_context); #ifndef LISP_FEATURE_WIN32 if ((signal == SIGILL) || (signal == SIGBUS) #ifndef LISP_FEATURE_LINUX @@ -1598,7 +1645,7 @@ static void unblock_me_trampoline(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(context,void_context); + SAVE_ERRNO(signal,context,void_context); sigset_t unblock; sigemptyset(&unblock); @@ -1611,7 +1658,7 @@ static void low_level_unblock_me_trampoline(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(context,void_context); + SAVE_ERRNO(signal,context,void_context); sigset_t unblock; sigemptyset(&unblock); @@ -1624,7 +1671,7 @@ static void low_level_handle_now_handler(int signal, siginfo_t *info, void *void_context) { - SAVE_ERRNO(context,void_context); + SAVE_ERRNO(signal,context,void_context); (*interrupt_low_level_handlers[signal])(signal, info, context); RESTORE_ERRNO; } Index: monitor.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/monitor.c,v retrieving revision 1.38 retrieving revision 1.39 diff -u -d -r1.38 -r1.39 --- monitor.c 17 Jan 2009 10:43:57 -0000 1.38 +++ monitor.c 11 May 2009 13:24:34 -0000 1.39 @@ -454,6 +454,10 @@ if (!ldb_in) { #ifndef LISP_FEATURE_WIN32 ldb_in = fopen("/dev/tty","r+"); + if (ldb_in == NULL) { + perror("Error opening /dev/tty"); + ldb_in = stdin; + } #else ldb_in = stdin; #endif Index: thread.c =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/thread.c,v retrieving revision 1.103 retrieving revision 1.104 diff -u -d -r1.103 -r1.104 --- thread.c 23 Mar 2009 11:26:51 -0000 1.103 +++ thread.c 11 May 2009 13:24:34 -0000 1.104 @@ -92,6 +92,7 @@ #ifdef LISP_FEATURE_GCC_TLS __thread struct thread *current_thread; #endif +pthread_key_t lisp_thread = 0; #endif #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) @@ -127,6 +128,9 @@ #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) lispobj *args = NULL; #endif +#ifdef LISP_FEATURE_SB_THREAD + pthread_setspecific(lisp_thread, (void *)1); +#endif function = th->no_tls_value_marker; th->no_tls_value_marker = NO_TLS_VALUE_MARKER_WIDETAG; if(arch_os_thread_init(th)==0) return 1; @@ -263,6 +267,7 @@ FSHOW((stderr,"/creating thread %lu\n", thread_self())); check_deferrables_blocked_or_lose(0); check_gc_signals_unblocked_or_lose(0); + pthread_setspecific(lisp_thread, (void *)1); function = th->no_tls_value_marker; th->no_tls_value_marker = NO_TLS_VALUE_MARKER_WIDETAG; if(arch_os_thread_init(th)==0) { @@ -492,6 +497,9 @@ void create_initial_thread(lispobj initial_function) { struct thread *th=create_thread_struct(initial_function); +#ifdef LISP_FEATURE_SB_THREAD + pthread_key_create(&lisp_thread, 0); +#endif if(th) { #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER setup_mach_exception_handling_thread(); Index: thread.h =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/runtime/thread.h,v retrieving revision 1.39 retrieving revision 1.40 diff -u -d -r1.39 -r1.40 --- thread.h 22 Mar 2009 21:45:04 -0000 1.39 +++ thread.h 11 May 2009 13:24:34 -0000 1.40 @@ -57,6 +57,7 @@ #endif extern int kill_safely(os_thread_t os_thread, int signal); +extern void kill_a_lisp_thread(int signal); #define THREAD_SLOT_OFFSET_WORDS(c) \ (offsetof(struct thread,c)/(sizeof (struct thread *))) @@ -68,6 +69,7 @@ extern struct thread *all_threads; extern int dynamic_values_bytes; +extern pthread_key_t lisp_thread; #if defined(LISP_FEATURE_DARWIN) #define CONTROL_STACK_ALIGNMENT_BYTES 8192 /* darwin wants page-aligned stacks */ |