~ chicken-core (chicken-5) 6cf5b12b275455ff9c9adfd9e7d6e0ffeed98478
commit 6cf5b12b275455ff9c9adfd9e7d6e0ffeed98478 Author: Peter Bex <peter.bex@xs4all.nl> AuthorDate: Thu Feb 13 21:20:20 2014 +0100 Commit: Christian Kellermann <ckeen@pestilenz.org> CommitDate: Fri Feb 14 12:48:06 2014 +0100 Block *all* signals while the global signal handler is running. Before, it would block just the signal that it was currently handling. This is problematic because different signals could interrupt the signal handler causing annoying race conditions on multi-CPU systems. Hopefully this will finally fix #877 properly. Signed-off-by: Christian Kellermann <ckeen@pestilenz.org> diff --git a/runtime.c b/runtime.c index f184d713..fdbc4d0b 100644 --- a/runtime.c +++ b/runtime.c @@ -738,11 +738,7 @@ int CHICKEN_initialize(int heap, int stack, int symbols, void *toplevel) if(!pass_serious_signals) { #ifdef HAVE_SIGACTION sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sigaddset(&sa.sa_mask, SIGBUS); - sigaddset(&sa.sa_mask, SIGFPE); - sigaddset(&sa.sa_mask, SIGILL); - sigaddset(&sa.sa_mask, SIGSEGV); + sigfillset(&sa.sa_mask); /* See note in C_establish_signal_handler() */ sa.sa_handler = global_signal_handler; C_sigaction(SIGBUS, &sa, NULL); C_sigaction(SIGFPE, &sa, NULL); @@ -4511,16 +4507,17 @@ C_regparm C_word C_fcall C_establish_signal_handler(C_word signum, C_word reason int sig = C_unfix(signum); #if defined(HAVE_SIGACTION) struct sigaction newsig; - - newsig.sa_flags = 0; - sigemptyset(&newsig.sa_mask); #endif if(reason == C_SCHEME_FALSE) C_signal(sig, SIG_IGN); else { signal_mapping_table[ sig ] = C_unfix(reason); #if defined(HAVE_SIGACTION) - sigaddset(&newsig.sa_mask, sig); + newsig.sa_flags = 0; + /* The global signal handler is used for all signals, and + manipulates a single queue. Don't allow other signals to + concurrently arrive while it's doing this, to avoid races. */ + sigfillset(&newsig.sa_mask); newsig.sa_handler = global_signal_handler; C_sigaction(sig, &newsig, NULL); #elseTrap