;-) 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