emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r116872: Handle sigmask better with nested signal ha


From: Paul Eggert
Subject: [Emacs-diffs] trunk r116872: Handle sigmask better with nested signal handlers.
Date: Tue, 25 Mar 2014 14:43:32 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 116872
revision-id: address@hidden
parent: address@hidden
fixes bug: http://debbugs.gnu.org/15561
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Tue 2014-03-25 07:43:26 -0700
message:
  Handle sigmask better with nested signal handlers.
  
  * atimer.c (sigmask_atimers): Remove.
  Remaining use rewritten to use body of this function.
  * atimer.c (block_atimers, unblock_atimers):
  * callproc.c (block_child_signal, unblock_child_signal):
  * sysdep.c (block_tty_out_signal, unblock_tty_out_signal):
  New arg OLDSET.  All callers changed.
  * atimer.c (block_atimers, unblock_atimers):
  * callproc.c (block_child_signal, unblock_child_signal):
  * keyboard.c (handle_interrupt):
  * sound.c (vox_configure, vox_close):
  Restore the old signal mask rather than unilaterally clearing bits
  from the mask, in case a handler is running within another
  handler.  All callers changed.
  * lisp.h, process.c, process.h, term.c:
  Adjust decls and callers to match new API.
  * sysdep.c (emacs_sigaction_init): Don't worry about masking SIGFPE;
  signal handlers aren't supposed to use floating point anyway.
  (handle_arith_signal): Unblock just SIGFPE rather than clearing mask.
modified:
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/atimer.c                   atimer.c-20091113204419-o5vbwnq5f7feedwu-1759
  src/callproc.c                 callproc.c-20091113204419-o5vbwnq5f7feedwu-248
  src/keyboard.c                 keyboard.c-20091113204419-o5vbwnq5f7feedwu-449
  src/lisp.h                     lisp.h-20091113204419-o5vbwnq5f7feedwu-253
  src/process.c                  process.c-20091113204419-o5vbwnq5f7feedwu-462
  src/process.h                  process.h-20091113204419-o5vbwnq5f7feedwu-272
  src/sound.c                    sound.c-20091113204419-o5vbwnq5f7feedwu-1323
  src/sysdep.c                   sysdep.c-20091113204419-o5vbwnq5f7feedwu-448
  src/term.c                     term.c-20091113204419-o5vbwnq5f7feedwu-220
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2014-03-23 21:58:41 +0000
+++ b/src/ChangeLog     2014-03-25 14:43:26 +0000
@@ -1,3 +1,25 @@
+2014-03-25  Paul Eggert  <address@hidden>
+
+       Handle sigmask better with nested signal handlers  (Bug#15561).
+       * atimer.c (sigmask_atimers): Remove.
+       Remaining use rewritten to use body of this function.
+       * atimer.c (block_atimers, unblock_atimers):
+       * callproc.c (block_child_signal, unblock_child_signal):
+       * sysdep.c (block_tty_out_signal, unblock_tty_out_signal):
+       New arg OLDSET.  All callers changed.
+       * atimer.c (block_atimers, unblock_atimers):
+       * callproc.c (block_child_signal, unblock_child_signal):
+       * keyboard.c (handle_interrupt):
+       * sound.c (vox_configure, vox_close):
+       Restore the old signal mask rather than unilaterally clearing bits
+       from the mask, in case a handler is running within another
+       handler.  All callers changed.
+       * lisp.h, process.c, process.h, term.c:
+       Adjust decls and callers to match new API.
+       * sysdep.c (emacs_sigaction_init): Don't worry about masking SIGFPE;
+       signal handlers aren't supposed to use floating point anyway.
+       (handle_arith_signal): Unblock just SIGFPE rather than clearing mask.
+
 2014-03-23  Daniel Colascione  <address@hidden>
 
        Split gc_sweep into discrete functions for legibility and better

=== modified file 'src/atimer.c'
--- a/src/atimer.c      2014-01-01 07:43:34 +0000
+++ b/src/atimer.c      2014-03-25 14:43:26 +0000
@@ -50,22 +50,17 @@
 /* Block/unblock SIGALRM.  */
 
 static void
-sigmask_atimers (int how)
+block_atimers (sigset_t *oldset)
 {
   sigset_t blocked;
   sigemptyset (&blocked);
   sigaddset (&blocked, SIGALRM);
-  pthread_sigmask (how, &blocked, 0);
-}
-static void
-block_atimers (void)
-{
-  sigmask_atimers (SIG_BLOCK);
-}
-static void
-unblock_atimers (void)
-{
-  sigmask_atimers (SIG_UNBLOCK);
+  pthread_sigmask (SIG_BLOCK, &blocked, oldset);
+}
+static void
+unblock_atimers (sigset_t const *oldset)
+{
+  pthread_sigmask (SIG_SETMASK, oldset, 0);
 }
 
 /* Function prototypes.  */
@@ -98,6 +93,7 @@
              atimer_callback fn, void *client_data)
 {
   struct atimer *t;
+  sigset_t oldset;
 
   /* Round TIME up to the next full second if we don't have
      itimers.  */
@@ -122,7 +118,7 @@
   t->fn = fn;
   t->client_data = client_data;
 
-  block_atimers ();
+  block_atimers (&oldset);
 
   /* Compute the timer's expiration time.  */
   switch (type)
@@ -143,7 +139,7 @@
 
   /* Insert the timer in the list of active atimers.  */
   schedule_atimer (t);
-  unblock_atimers ();
+  unblock_atimers (&oldset);
 
   /* Arrange for a SIGALRM at the time the next atimer is ripe.  */
   set_alarm ();
@@ -158,8 +154,9 @@
 cancel_atimer (struct atimer *timer)
 {
   int i;
+  sigset_t oldset;
 
-  block_atimers ();
+  block_atimers (&oldset);
 
   for (i = 0; i < 2; ++i)
     {
@@ -186,7 +183,7 @@
        }
     }
 
-  unblock_atimers ();
+  unblock_atimers (&oldset);
 }
 
 
@@ -217,7 +214,8 @@
 void
 stop_other_atimers (struct atimer *t)
 {
-  block_atimers ();
+  sigset_t oldset;
+  block_atimers (&oldset);
 
   if (t)
     {
@@ -242,7 +240,7 @@
 
   stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
   atimers = t;
-  unblock_atimers ();
+  unblock_atimers (&oldset);
 }
 
 
@@ -256,8 +254,9 @@
     {
       struct atimer *t = atimers;
       struct atimer *next;
+      sigset_t oldset;
 
-      block_atimers ();
+      block_atimers (&oldset);
       atimers = stopped_atimers;
       stopped_atimers = NULL;
 
@@ -268,7 +267,7 @@
          t = next;
        }
 
-      unblock_atimers ();
+      unblock_atimers (&oldset);
     }
 }
 
@@ -381,9 +380,10 @@
 {
   if (atimers)
     {
-      block_atimers ();
+      sigset_t oldset;
+      block_atimers (&oldset);
       run_timers ();
-      unblock_atimers ();
+      unblock_atimers (&oldset);
     }
 }
 

=== modified file 'src/callproc.c'
--- a/src/callproc.c    2014-03-22 23:47:20 +0000
+++ b/src/callproc.c    2014-03-25 14:43:26 +0000
@@ -108,20 +108,20 @@
 /* Block SIGCHLD.  */
 
 void
-block_child_signal (void)
+block_child_signal (sigset_t *oldset)
 {
   sigset_t blocked;
   sigemptyset (&blocked);
   sigaddset (&blocked, SIGCHLD);
-  pthread_sigmask (SIG_BLOCK, &blocked, 0);
+  pthread_sigmask (SIG_BLOCK, &blocked, oldset);
 }
 
 /* Unblock SIGCHLD.  */
 
 void
-unblock_child_signal (void)
+unblock_child_signal (sigset_t const *oldset)
 {
-  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+  pthread_sigmask (SIG_SETMASK, oldset, 0);
 }
 
 /* Return the current buffer's working directory, or the home
@@ -162,7 +162,8 @@
 void
 record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile)
 {
-  block_child_signal ();
+  sigset_t oldset;
+  block_child_signal (&oldset);
 
   if (p->alive)
     {
@@ -171,7 +172,7 @@
       kill (- p->pid, SIGKILL);
     }
 
-  unblock_child_signal ();
+  unblock_child_signal (&oldset);
 }
 
 /* Clean up files, file descriptors and processes created by Fcall_process.  */
@@ -313,6 +314,7 @@
   char *tempfile = NULL;
   int pid;
 #else
+  sigset_t oldset;
   pid_t pid;
 #endif
   int child_errno;
@@ -629,7 +631,7 @@
 #ifndef MSDOS
 
   block_input ();
-  block_child_signal ();
+  block_child_signal (&oldset);
 
 #ifdef WINDOWSNT
   pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir);
@@ -671,7 +673,7 @@
 
   if (pid == 0)
     {
-      unblock_child_signal ();
+      unblock_child_signal (&oldset);
 
       setsid ();
 
@@ -707,7 +709,7 @@
        }
     }
 
-  unblock_child_signal ();
+  unblock_child_signal (&oldset);
   unblock_input ();
 
 #endif /* not MSDOS */

=== modified file 'src/keyboard.c'
--- a/src/keyboard.c    2014-02-24 14:26:49 +0000
+++ b/src/keyboard.c    2014-03-25 14:43:26 +0000
@@ -10295,6 +10295,9 @@
 handle_interrupt (bool in_signal_handler)
 {
   char c;
+  sigset_t blocked;
+  sigemptyset (&blocked);
+  sigaddset (&blocked, SIGINT);
 
   cancel_echoing ();
 
@@ -10306,9 +10309,6 @@
          /* 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);
        }
 
@@ -10393,7 +10393,7 @@
          struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
          immediate_quit = 0;
-         pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+         pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
          saved = gl_state;
          GCPRO4 (saved.object, saved.global_code,
                  saved.current_syntax_table, saved.old_prop);
@@ -10414,7 +10414,7 @@
         }
     }
 
-  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+  pthread_sigmask (SIG_UNBLOCK, &blocked, 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

=== modified file 'src/lisp.h'
--- a/src/lisp.h        2014-03-21 07:26:47 +0000
+++ b/src/lisp.h        2014-03-25 14:43:26 +0000
@@ -4238,8 +4238,8 @@
 extern void sys_subshell (void);
 extern void sys_suspend (void);
 extern void discard_tty_input (void);
-extern void block_tty_out_signal (void);
-extern void unblock_tty_out_signal (void);
+extern void block_tty_out_signal (sigset_t *);
+extern void unblock_tty_out_signal (sigset_t const *);
 extern void init_sys_modes (struct tty_display_info *);
 extern void reset_sys_modes (struct tty_display_info *);
 extern void init_all_sys_modes (void);

=== modified file 'src/process.c'
--- a/src/process.c     2014-03-23 05:15:48 +0000
+++ b/src/process.c     2014-03-25 14:43:26 +0000
@@ -1663,6 +1663,7 @@
   bool pty_flag = 0;
   char pty_name[PTY_NAME_SIZE];
   Lisp_Object lisp_pty_name = Qnil;
+  sigset_t oldset;
 
   inchannel = outchannel = -1;
 
@@ -1728,7 +1729,7 @@
   setup_process_coding_systems (process);
 
   block_input ();
-  block_child_signal ();
+  block_child_signal (&oldset);
 
 #ifndef WINDOWSNT
   /* vfork, and prevent local vars from being clobbered by the vfork.  */
@@ -1852,7 +1853,7 @@
       signal (SIGPIPE, SIG_DFL);
 
       /* Stop blocking SIGCHLD in the child.  */
-      unblock_child_signal ();
+      unblock_child_signal (&oldset);
 
       if (pty_flag)
        child_setup_tty (xforkout);
@@ -1871,7 +1872,7 @@
     p->alive = 1;
 
   /* Stop blocking in the parent.  */
-  unblock_child_signal ();
+  unblock_child_signal (&oldset);
   unblock_input ();
 
   if (pid < 0)
@@ -7070,8 +7071,9 @@
 catch_child_signal (void)
 {
   struct sigaction action, old_action;
+  sigset_t oldset;
   emacs_sigaction_init (&action, deliver_child_signal);
-  block_child_signal ();
+  block_child_signal (&oldset);
   sigaction (SIGCHLD, &action, &old_action);
   eassert (! (old_action.sa_flags & SA_SIGINFO));
 
@@ -7080,7 +7082,7 @@
       = (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN
         ? dummy_handler
         : old_action.sa_handler);
-  unblock_child_signal ();
+  unblock_child_signal (&oldset);
 }
 
 

=== modified file 'src/process.h'
--- a/src/process.h     2014-01-01 07:43:34 +0000
+++ b/src/process.h     2014-03-25 14:43:26 +0000
@@ -213,8 +213,8 @@
 
 /* Defined in callproc.c.  */
 
-extern void block_child_signal (void);
-extern void unblock_child_signal (void);
+extern void block_child_signal (sigset_t *);
+extern void unblock_child_signal (sigset_t const *);
 extern Lisp_Object encode_current_directory (void);
 extern void record_kill_process (struct Lisp_Process *, Lisp_Object);
 

=== modified file 'src/sound.c'
--- a/src/sound.c       2014-01-01 07:43:34 +0000
+++ b/src/sound.c       2014-03-25 14:43:26 +0000
@@ -702,7 +702,7 @@
 {
   int val;
 #ifdef USABLE_SIGIO
-  sigset_t blocked;
+  sigset_t oldset, blocked;
 #endif
 
   eassert (sd->fd >= 0);
@@ -714,7 +714,7 @@
 #ifdef USABLE_SIGIO
   sigemptyset (&blocked);
   sigaddset (&blocked, SIGIO);
-  pthread_sigmask (SIG_BLOCK, &blocked, 0);
+  pthread_sigmask (SIG_BLOCK, &blocked, &oldset);
 #endif
 
   val = sd->format;
@@ -748,7 +748,7 @@
 
   turn_on_atimers (1);
 #ifdef USABLE_SIGIO
-  pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
+  pthread_sigmask (SIG_SETMASK, &oldset, 0);
 #endif
 }
 
@@ -764,10 +764,10 @@
         be interrupted by a signal.  Block the ones we know to cause
         troubles.  */
 #ifdef USABLE_SIGIO
-      sigset_t blocked;
+      sigset_t blocked, oldset;
       sigemptyset (&blocked);
       sigaddset (&blocked, SIGIO);
-      pthread_sigmask (SIG_BLOCK, &blocked, 0);
+      pthread_sigmask (SIG_BLOCK, &blocked, &oldset);
 #endif
       turn_on_atimers (0);
 
@@ -776,7 +776,7 @@
 
       turn_on_atimers (1);
 #ifdef USABLE_SIGIO
-      pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
+      pthread_sigmask (SIG_SETMASK, &oldset, 0);
 #endif
 
       /* Close the device.  */

=== modified file 'src/sysdep.c'
--- a/src/sysdep.c      2014-01-01 07:43:34 +0000
+++ b/src/sysdep.c      2014-03-25 14:43:26 +0000
@@ -692,21 +692,21 @@
 /* Block and unblock SIGTTOU.  */
 
 void
-block_tty_out_signal (void)
+block_tty_out_signal (sigset_t *oldset)
 {
 #ifdef SIGTTOU
   sigset_t blocked;
   sigemptyset (&blocked);
   sigaddset (&blocked, SIGTTOU);
-  pthread_sigmask (SIG_BLOCK, &blocked, 0);
+  pthread_sigmask (SIG_BLOCK, &blocked, oldset);
 #endif
 }
 
 void
-unblock_tty_out_signal (void)
+unblock_tty_out_signal (sigset_t const *oldset)
 {
 #ifdef SIGTTOU
-  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+  pthread_sigmask (SIG_SETMASK, oldset, 0);
 #endif
 }
 
@@ -721,10 +721,11 @@
 tcsetpgrp_without_stopping (int fd, pid_t pgid)
 {
 #ifdef SIGTTOU
+  sigset_t oldset;
   block_input ();
-  block_tty_out_signal ();
+  block_tty_out_signal (&oldset);
   tcsetpgrp (fd, pgid);
-  unblock_tty_out_signal ();
+  unblock_tty_out_signal (&oldset);
   unblock_input ();
 #endif
 }
@@ -1525,9 +1526,6 @@
 #endif
     }
 
-  if (! IEEE_FLOATING_POINT)
-    sigaddset (&action->sa_mask, SIGFPE);
-
   action->sa_handler = handler;
   action->sa_flags = emacs_sigaction_flags ();
 }
@@ -1643,7 +1641,10 @@
 static _Noreturn void
 handle_arith_signal (int sig)
 {
-  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+  sigset_t blocked;
+  sigemptyset (&blocked);
+  sigaddset (&blocked, sig);
+  pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
   xsignal0 (Qarith_error);
 }
 

=== modified file 'src/term.c'
--- a/src/term.c        2014-03-23 08:29:43 +0000
+++ b/src/term.c        2014-03-25 14:43:26 +0000
@@ -3944,9 +3944,10 @@
       /* setsid failed, presumably because Emacs is already a process
         group leader.  Fall back on the obsolescent way to dissociate
         a controlling tty.  */
-      block_tty_out_signal ();
+      sigset_t oldset;
+      block_tty_out_signal (&oldset);
       ioctl (fd, TIOCNOTTY, 0);
-      unblock_tty_out_signal ();
+      unblock_tty_out_signal (&oldset);
 #endif
     }
 }
@@ -3970,6 +3971,7 @@
   int status;
   struct tty_display_info *tty = NULL;
   struct terminal *terminal = NULL;
+  sigset_t oldset;
   bool ctty = false;  /* True if asked to open controlling tty.  */
 
   if (!terminal_type)
@@ -4059,11 +4061,11 @@
 
   /* On some systems, tgetent tries to access the controlling
      terminal.  */
-  block_tty_out_signal ();
+  block_tty_out_signal (&oldset);
   status = tgetent (tty->termcap_term_buffer, terminal_type);
   if (tty->termcap_term_buffer[TERMCAP_BUFFER_SIZE - 1])
     emacs_abort ();
-  unblock_tty_out_signal ();
+  unblock_tty_out_signal (&oldset);
 
   if (status < 0)
     {


reply via email to

[Prev in Thread] Current Thread [Next in Thread]