~ chicken-core (chicken-5) 72165012f47068a5eeae3c5ac6410f9e5727e54c
commit 72165012f47068a5eeae3c5ac6410f9e5727e54c Author: Jörg F. Wittenberger <Joerg.Wittenberger@softeyes.net> AuthorDate: Thu Jan 14 20:09:40 2016 +0100 Commit: Evan Hanson <evhan@foldling.org> CommitDate: Fri Jan 15 09:10:09 2016 +1300 Allow signal handlers to be dispatched to multiple threads To avoid clobbering the saved_stack_limit when multiple signals are dispatched in parallel: 1. Remember C_stack_limit 2. Test pending_interrupts_count 3. Increment pending_interrupts_count 4. Write remembered value to saved_stack_limit Signed-off-by: Evan Hanson <evhan@foldling.org> Signed-off-by: Peter Bex <peter@more-magic.net> diff --git a/NEWS b/NEWS index 5d85191c..4336f0f0 100644 --- a/NEWS +++ b/NEWS @@ -41,6 +41,8 @@ - CHICKEN now supports the Linux X32 ABI (thanks to Sven Hartrumpf). - Runtime system: + - Delivery of signals in other OS-level threads is now dealt with + in a more robust way (#1232) (thanks to Joerg Wittenberger). - Compiled programs with large literals won't crash on startup (#1221). - Comparisons of closures now behave in a stable way, whether or not the code was compiled with the -no-lambda-info option (#1041). diff --git a/runtime.c b/runtime.c index 25ba96a2..78bb3a65 100644 --- a/runtime.c +++ b/runtime.c @@ -4850,20 +4850,24 @@ C_regparm void C_fcall C_paranoid_check_for_interrupt(void) C_regparm void C_fcall C_raise_interrupt(int reason) { + /* + * Save the value of C_stack_limit from before the interrupt is queued + * to ensure that multiple signals only ever cause saved_stack_limit + * to be assigned a value from when pending_interrupts_count was zero. + */ + C_word *stack_limit = C_stack_limit; + if(C_interrupts_enabled) { if(pending_interrupts_count == 0 && !handling_interrupts) { - /* Force the next stack check to fail by faking a "full" stack. - That causes save_and_reclaim() to be called, which will - invoke handle_interrupt() (which restores the stack limit). */ - saved_stack_limit = C_stack_limit; - -#if C_STACK_GROWS_DOWNWARD - C_stack_limit = C_stack_pointer + 1000; -#else - C_stack_limit = C_stack_pointer - 1000; -#endif - interrupt_time = C_cpu_milliseconds(); pending_interrupts[ pending_interrupts_count++ ] = reason; + /* + * Force the next stack check to fail by faking a "full" stack. + * This causes save_and_reclaim() to be called, which invokes + * handle_interrupt(), which restores the stack limit. + */ + saved_stack_limit = stack_limit; + C_stack_limit = stack_bottom; + interrupt_time = C_cpu_milliseconds(); } else if(pending_interrupts_count < MAX_PENDING_INTERRUPTS) { int i; /*Trap