~ 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