~ chicken-core (chicken-5) 82946832fc3401ee896140a46b101eed34f8fb28
commit 82946832fc3401ee896140a46b101eed34f8fb28
Author: Jörg F. Wittenberger <Joerg.Wittenberger@softeyes.net>
AuthorDate: Thu Dec 3 10:52:06 2015 +0100
Commit: Peter Bex <peter@more-magic.net>
CommitDate: Thu Jan 14 20:09:05 2016 +0100
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 b3d82789..5de03cf9 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,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 d65c3a59..112314d3 100644
--- a/runtime.c
+++ b/runtime.c
@@ -4431,20 +4431,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