~ 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