;-)

as promised:

Am 02.12.2015 um 14:57 schrieb Jörg F. Wittenberger:
> No more patches today.  This again is no good
> because it allocates a slot in pending_interrupts, but doesn't - and
> can't deallocate it.

No more patches yesterday.  This one sustained the test to sleep one
night over it.

It only fixes two problems with the current code: a) smashing
C_stack_limit with a pointer into some other threads stack  b) multiple
updates to saved_stack_limit with a value from C_stack_limit.

a) does typically result in a segfault and b) will reduce the effective
stack size until endlessly looping when it reaches zero.  Whereby (b) is
exacerbated by the fix to (a) to a single step till zero.

Since I found this whole signal handling a bit confusing, I added a few
lines of comments to the code.

Please try this time.

At this point the patch asserts that the chicken process will not fail.
 It does _not_ address the fact that the code will loose signals.  It
did before, it does now.

One more question.  I would have expected chicken to store signals
received while C_interrupts_enabled==0 and deliver them at some point
after C_interrupts_enabled becomes true.  Why are those signals ignored?

Have a good day

/Jörg
From 5594268869809d7cd7d4ee85199a88894aa1e49b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20F=2E=20Wittenberger?=
 <joerg.wittenber...@softeyes.net>
Date: Thu, 3 Dec 2015 10:52:06 +0100
Subject: [PATCH] Allow signal handlers to be dispatched to multiple threads.

---
 runtime.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/runtime.c b/runtime.c
index 9d93476..78d098f 100644
--- a/runtime.c
+++ b/runtime.c
@@ -4394,20 +4394,25 @@ C_regparm void C_fcall C_paranoid_check_for_interrupt(void)
 
 C_regparm void C_fcall C_raise_interrupt(int reason)
 {
+  /* If signals are dispatched to several threads in parallel more
+     than one may take this code path.  Make sure that at least no
+     thread will write a value to saved_stack_limit which was obtained
+     from C_stack_limit at a time when pending_interrupts_count was
+     not zero (and thus C_stack_limit possibly already updated from
+     the other thread).  We 1. remember C_stack_limit, 2. test
+     pending_interrupts_count==0, 3. set pending_interrupts_count,
+     4. write _the remembered_ value to saved_stack_limit. */
+  C_word *stack_limit = C_stack_limit;  // remember this first
   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.  That causes
+      save_and_reclaim() to be called, which will invoke
+      handle_interrupt() (which restores the stack limit). */
+      saved_stack_limit = stack_limit; /* first write the backup going to be restored */
+      C_stack_limit = stack_bottom;    /* then fake the full stack */
+      interrupt_time = C_cpu_milliseconds();
     } else if(pending_interrupts_count < MAX_PENDING_INTERRUPTS) {
       int i;
       /*
-- 
2.6.2

_______________________________________________
Chicken-hackers mailing list
Chicken-hackers@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-hackers

Reply via email to