From: Paul Eggert Date: Fri, 30 May 2014 04:12:08 +0000 (-0700) Subject: Don't let SIGINT handling block SIGCHLD indefinitely. X-Git-Tag: emacs-25.0.90~2612^2~709^2~838 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=8cf1e6e67926683e38809adced986d255124afd5;p=emacs.git Don't let SIGINT handling block SIGCHLD indefinitely. * atimer.c (block_atimers): * callproc.c (block_child_signal): Block SIGINT too; otherwise, its handler might now unblock signals that it shouldn't. * keyboard.c (read_char): Clear signal mask, since we may be in a SIGINT handler, and many signals may be masked. * keyboard.c (handle_interrupt): * sysdep.c (handle_arith_signal): Clear signal mask instead of just unblocking the signal that was received, since several signals may be blocked at this point. Fixes: debbugs:17561 --- diff --git a/src/ChangeLog b/src/ChangeLog index 33952e159bf..6ecf7dbee99 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2014-05-30 Paul Eggert + + Don't let SIGINT handling block SIGCHLD indefinitely (Bug#17561). + * atimer.c (block_atimers): + * callproc.c (block_child_signal): Block SIGINT too; + otherwise, its handler might now unblock signals that it shouldn't. + * keyboard.c (read_char): Clear signal mask, since we may + be in a SIGINT handler, and many signals may be masked. + * keyboard.c (handle_interrupt): + * sysdep.c (handle_arith_signal): + Clear signal mask instead of just unblocking the signal that + was received, since several signals may be blocked at this point. + 2014-05-29 Eli Zaretskii * Makefile.in (TEMACS_POST_LINK): Remove target. diff --git a/src/atimer.c b/src/atimer.c index a5a2b0714e3..e457a7fcf1c 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -55,6 +55,7 @@ block_atimers (sigset_t *oldset) sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGALRM); + sigaddset (&blocked, SIGINT); pthread_sigmask (SIG_BLOCK, &blocked, oldset); } static void @@ -404,7 +405,6 @@ turn_on_atimers (bool on) void init_atimer (void) { - struct sigaction action; #ifdef HAVE_ITIMERSPEC struct sigevent sigev; sigev.sigev_notify = SIGEV_SIGNAL; @@ -413,7 +413,9 @@ init_atimer (void) alarm_timer_ok = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0; #endif free_atimers = stopped_atimers = atimers = NULL; - /* pending_signals is initialized in init_keyboard.*/ + + /* pending_signals is initialized in init_keyboard. */ + struct sigaction action; emacs_sigaction_init (&action, handle_alarm_signal); sigaction (SIGALRM, &action, 0); } diff --git a/src/callproc.c b/src/callproc.c index a2c52e5b5ba..0506bf53a25 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -115,6 +115,7 @@ block_child_signal (sigset_t *oldset) sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); + sigaddset (&blocked, SIGINT); pthread_sigmask (SIG_BLOCK, &blocked, oldset); } diff --git a/src/keyboard.c b/src/keyboard.c index e92c86b7dbf..17bfc81b82f 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -2664,6 +2664,7 @@ read_char (int commandflag, Lisp_Object map, /* We must have saved the outer value of getcjmp here, so restore it now. */ restore_getcjmp (save_jump); + pthread_sigmask (SIG_SETMASK, &empty_mask, 0); unbind_to (jmpcount, Qnil); XSETINT (c, quit_char); internal_last_event_frame = selected_frame; @@ -10323,9 +10324,6 @@ static void handle_interrupt (bool in_signal_handler) { char c; - sigset_t blocked; - sigemptyset (&blocked); - sigaddset (&blocked, SIGINT); cancel_echoing (); @@ -10337,6 +10335,9 @@ handle_interrupt (bool in_signal_handler) /* If SIGINT isn't blocked, don't let us be interrupted by a SIGINT. It might be harmful due to non-reentrancy in I/O functions. */ + sigset_t blocked; + sigemptyset (&blocked); + sigaddset (&blocked, SIGINT); pthread_sigmask (SIG_BLOCK, &blocked, 0); } @@ -10421,7 +10422,7 @@ handle_interrupt (bool in_signal_handler) struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; immediate_quit = 0; - pthread_sigmask (SIG_UNBLOCK, &blocked, 0); + pthread_sigmask (SIG_SETMASK, &empty_mask, 0); saved = gl_state; GCPRO4 (saved.object, saved.global_code, saved.current_syntax_table, saved.old_prop); @@ -10442,7 +10443,7 @@ handle_interrupt (bool in_signal_handler) } } - pthread_sigmask (SIG_UNBLOCK, &blocked, 0); + pthread_sigmask (SIG_SETMASK, &empty_mask, 0); /* TODO: The longjmp in this call throws the NS event loop integration off, and it seems to do fine without this. Probably some attention diff --git a/src/sysdep.c b/src/sysdep.c index e5b29205e96..573d419970d 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1645,10 +1645,7 @@ deliver_fatal_thread_signal (int sig) static _Noreturn void handle_arith_signal (int sig) { - sigset_t blocked; - sigemptyset (&blocked); - sigaddset (&blocked, sig); - pthread_sigmask (SIG_UNBLOCK, &blocked, 0); + pthread_sigmask (SIG_SETMASK, &empty_mask, 0); xsignal0 (Qarith_error); }