diff --git a/src/signal_handler.c b/src/signal_handler.c index f0b410375e4781582e1b28369092ddec6be165d5..08dd1e7790b194f976df2e2fd9f7e6ce7e1df4b4 100644 --- a/src/signal_handler.c +++ b/src/signal_handler.c @@ -372,6 +372,7 @@ static int set_priority( int pid, char *to ); static struct svalue signal_callbacks[MAX_SIGNALS]; +static sig_atomic_t signal_masks[MAX_SIGNALS]; static void (*default_signals[MAX_SIGNALS])(INT32); static struct callback *signal_evaluator_callback =0; @@ -783,26 +784,16 @@ void my_signal(int sig, sigfunctype fun) -static int signalling=0; - -static void unset_signalling(void *UNUSED(notused)) { signalling=0; } - PMOD_EXPORT void check_signals(struct callback *UNUSED(foo), void *UNUSED(bar), void *UNUSED(gazonk)) { - ONERROR ebuf; - int num_callbacks = 0; #ifdef PIKE_DEBUG extern int d_flag; if(d_flag>5) do_debug(); #endif - - if(QUICK_CHECK_FIFO(sig, unsigned char) && !signalling) + if (QUICK_CHECK_FIFO(sig, unsigned char)) { unsigned char sig = ~0; - signalling=1; - - SET_ONERROR(ebuf,unset_signalling,0); while (sig_pop(&sig)) { @@ -825,33 +816,38 @@ PMOD_EXPORT void check_signals(struct callback *UNUSED(foo), void *UNUSED(bar), } #endif - if(SAFE_IS_ZERO(signal_callbacks + sig)) - { - if(default_signals[sig]) - default_signals[sig](sig); - }else{ - push_svalue(signal_callbacks + sig); - push_int(sig); - num_callbacks++; - } - } - - CALL_AND_UNSET_ONERROR(ebuf); + if (!signal_masks[sig]) { + signal_masks[sig] = 1; - /* Call the Pike-level callbacks in - * a context where signals are allowed. - */ - while(num_callbacks--) { - JMP_BUF recovery; - free_svalue(&throw_value); - mark_free_svalue(&throw_value); - if (SETJMP_SP(recovery, 2)) { - call_handle_error(); + do { + /* NB: We check this every loop in case the + * Pike-level signal handler has been + * disabled during the call. */ + if(SAFE_IS_ZERO(signal_callbacks + sig)) + { + if(default_signals[sig]) + default_signals[sig](sig); + } else { + JMP_BUF recovery; + free_svalue(&throw_value); + mark_free_svalue(&throw_value); + if (SETJMP_SP(recovery, 0)) { + call_handle_error(); + } else { + push_svalue(signal_callbacks + sig); + push_int(sig); + f_call_function(2); + pop_stack(); + } + UNSETJMP(recovery); + } + } while (--signal_masks[sig]); } else { - f_call_function(2); - pop_stack(); + /* Signal handler is being called somewhere else. + * Make it repeat when finished. + */ + signal_masks[sig] = 2; } - UNSETJMP(recovery); } } }