diff --git a/libguile/scmsigs.c b/libguile/scmsigs.c index 943327303..c4060070b 100644 --- a/libguile/scmsigs.c +++ b/libguile/scmsigs.c @@ -108,10 +108,20 @@ static SIGRETTYPE (*orig_handlers[NSIG])(int); #endif static SCM -close_1 (SCM proc, SCM arg) +handler_to_async (SCM handler, int signum) { - return scm_primitive_eval_x (scm_list_3 (scm_sym_lambda, SCM_EOL, - scm_list_2 (proc, arg))); + if (scm_is_false (handler)) + return SCM_BOOL_F; + else + { + SCM async = scm_primitive_eval_x (scm_list_3 (scm_sym_lambda, SCM_EOL, + scm_list_2 (handler, + scm_from_int (signum)))); +#if !SCM_USE_PTHREAD_THREADS + async = scm_cons (async, SCM_BOOL_F); +#endif + return async; + } } #if SCM_USE_PTHREAD_THREADS @@ -239,23 +249,10 @@ ensure_signal_delivery_thread () #endif /* !SCM_USE_PTHREAD_THREADS */ static void -install_handler (int signum, SCM thread, SCM handler) +install_handler (int signum, SCM thread, SCM handler, SCM async) { - if (scm_is_false (handler)) - { - SCM_SIMPLE_VECTOR_SET (*signal_handlers, signum, SCM_BOOL_F); - SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs, signum, SCM_BOOL_F); - } - else - { - SCM async = close_1 (handler, scm_from_int (signum)); -#if !SCM_USE_PTHREAD_THREADS - async = scm_cons (async, SCM_BOOL_F); -#endif - SCM_SIMPLE_VECTOR_SET (*signal_handlers, signum, handler); - SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs, signum, async); - } - + SCM_SIMPLE_VECTOR_SET (*signal_handlers, signum, handler); + SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs, signum, async); SCM_SIMPLE_VECTOR_SET (signal_handler_threads, signum, thread); } @@ -308,6 +305,7 @@ SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0, int save_handler = 0; SCM old_handler; + SCM async; csig = scm_to_signed_integer (signum, 0, NSIG-1); @@ -334,6 +332,10 @@ SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0, SCM_MISC_ERROR ("thread has already exited", SCM_EOL); } + /* Allocate upfront, as we can't do it inside the critical + section. */ + async = handler_to_async (handler, csig); + ensure_signal_delivery_thread (); SCM_CRITICAL_SECTION_START; @@ -351,7 +353,7 @@ SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0, #else chandler = (SIGRETTYPE (*) (int)) handler_int; #endif - install_handler (csig, SCM_BOOL_F, SCM_BOOL_F); + install_handler (csig, SCM_BOOL_F, SCM_BOOL_F, async); } else SCM_OUT_OF_RANGE (2, handler); @@ -366,7 +368,7 @@ SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0, { action = orig_handlers[csig]; orig_handlers[csig].sa_handler = SIG_ERR; - install_handler (csig, SCM_BOOL_F, SCM_BOOL_F); + install_handler (csig, SCM_BOOL_F, SCM_BOOL_F, async); } #else if (orig_handlers[csig] == SIG_ERR) @@ -375,7 +377,7 @@ SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0, { chandler = orig_handlers[csig]; orig_handlers[csig] = SIG_ERR; - install_handler (csig, SCM_BOOL_F, SCM_BOOL_F); + install_handler (csig, SCM_BOOL_F, SCM_BOOL_F, async); } #endif } @@ -391,7 +393,7 @@ SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0, if (orig_handlers[csig] == SIG_ERR) save_handler = 1; #endif - install_handler (csig, thread, handler); + install_handler (csig, thread, handler, async); } /* XXX - Silently ignore setting handlers for `program error signals'