Subject: Re: Signal-handler cleanup for Emacs

From: Paul Eggert <[email-masked]>
Date: Mon, 03 Sep 2012 01:16:08 -0700

On 09/02/2012 02:20 PM, Eli Zaretskii wrote:

> If that's the problem, then fix that, by changing the type.

If I understand this suggestion correctly, it's not practical.
GNU/Linux sigblock returns 'int', but its signal masks require 1024
bits, too wide for 'int'.  This is why sigblock has been removed from
POSIX and is documented as obsolete in GNU/Linux.

> Changes come at a cost, which should be justified.

My point was that the new version is smaller and faster.
How much smaller and faster doesn't matter much, as the primary
justification for the change is to reduce the confusion caused by
the current setup.

> I could go with replacing 'signal' etc. with their modern Posix
> replacements

OK, thanks, I reworked the patch to implement that suggestion.
I also modified it a bit in other ways, to boost the performance
a bit (as that suggestion caused a small performance hit).  The
result is attached.  I expect the Windows port will need a few
tweaks.
=== modified file 'ChangeLog'
--- ChangeLog	2012-09-02 11:13:24 +0000
+++ ChangeLog	2012-09-03 01:55:39 +0000
@@ -1,3 +1,10 @@
+2012-09-03  Paul Eggert  <[email-masked]>
+
+	Signal-handler cleanup (Bug#12327).
+	* configure.ac (PTY_OPEN, PTY_TTY_NAME_SPRINTF):
+	Adjust to syssignal.h changes.
+	(SIGNAL_H_AB): Remove; no longer needed.
+
 2012-09-02  Jan Djärv  <[email-masked]>
 
 	* configure.ac (HAVE_GOBJECT): Check for gobject-2.0 (Bug#12332).

=== modified file 'configure.ac'
--- configure.ac	2012-09-02 11:13:24 +0000
+++ configure.ac	2012-09-03 01:56:28 +0000
@@ -3450,7 +3450,7 @@
   cygwin )
     AC_DEFINE(PTY_ITERATION, [int i; for (i = 0; i < 1; i++)])
     dnl multi-line AC_DEFINEs are hard. :(
-    AC_DEFINE(PTY_OPEN, [ do { int dummy; SIGMASKTYPE mask; mask = sigblock (sigmask (SIGCHLD)); if (-1 == openpty (&fd, &dummy, pty_name, 0, 0)) fd = -1; sigsetmask (mask); if (fd >= 0) emacs_close (dummy); } while (0)])
+    AC_DEFINE(PTY_OPEN, [ do { int dummy; sigset_t blocked, procmask; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, &procmask); if (-1 == openpty (&fd, &dummy, pty_name, 0, 0)) fd = -1; pthread_sigmask (SIG_SETMASK, &procmask, 0); if (fd >= 0) emacs_close (dummy); } while (0)])
     AC_DEFINE(PTY_NAME_SPRINTF, [])
     AC_DEFINE(PTY_TTY_NAME_SPRINTF, [])
     ;;
@@ -3479,7 +3479,7 @@
       AC_DEFINE(PTY_ITERATION, [int i; for (i = 0; i < 1; i++)])
       dnl Note that grantpt and unlockpt may fork.  We must block SIGCHLD
       dnl to prevent sigchld_handler from intercepting the child's death.
-      AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptyname; sigblock (sigmask (SIGCHLD)); if (grantpt (fd) == -1 || unlockpt (fd) == -1 || !(ptyname = ptsname(fd))) { sigunblock (sigmask (SIGCHLD)); close (fd); return -1; } snprintf (pty_name, sizeof pty_name, "%s", ptyname); sigunblock (sigmask (SIGCHLD)); }])
+      AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptyname = 0; sigset_t blocked, procmask; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, &procmask); if (grantpt (fd) != -1 && unlockpt (fd) != -1) ptyname = ptsname(fd); pthread_sigmask (SIG_SETMASK, &procmask, 0); if (!ptyname) { close (fd); return -1; } snprintf (pty_name, sizeof pty_name, "%s", ptyname); }])
       dnl if HAVE_POSIX_OPENPT
       if test "x$ac_cv_func_posix_openpt" = xyes; then
         AC_DEFINE(PTY_OPEN, [fd = posix_openpt (O_RDWR | O_NOCTTY)])
@@ -3524,18 +3524,15 @@
     ;;
 
   sol2* )
-    dnl Uses sigblock/sigunblock rather than sighold/sigrelse,
-    dnl which appear to be BSD4.1 specific.  It may also be appropriate
-    dnl for SVR4.x (x<2) but I'm not sure.   [email-masked]
     dnl On SysVr4, grantpt(3) forks a subprocess, so keep sigchld_handler()
     dnl from intercepting that death.  If any child but grantpt's should die
     dnl within, it should be caught after sigrelse(2).
-    AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptsname (int), *ptyname; sigblock (sigmask (SIGCLD)); if (grantpt (fd) == -1) { emacs_close (fd); return -1; } sigunblock (sigmask (SIGCLD)); if (unlockpt (fd) == -1) { emacs_close (fd); return -1; } if (!(ptyname = ptsname (fd))) { emacs_close (fd); return -1; } snprintf (pty_name, sizeof pty_name, "%s", ptyname); }])
+    AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked, procmask; sigemptyset (&blocked); sigaddset (&blocked, SIGCLD); pthread_sigmask (SIG_BLOCK, &blocked, &procmask); grantpt_result = grantpt (fd); pthread_sigmask (SIG_SETMASK, &procmask, 0); if (grantpt_result == -1 || unlockpt (fd) == -1 || !(ptyname = ptsname (fd))) { emacs_close (fd); return -1; } snprintf (pty_name, sizeof pty_name, "%s", ptyname); }])
     ;;
 
   unixware )
     dnl Comments are as per sol2*.
-    AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptsname (int), *ptyname; sigblock(sigmask(SIGCLD)); if (grantpt(fd) == -1) fatal("could not grant slave pty"); sigunblock(sigmask(SIGCLD)); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, sizeof pty_name, "%s", ptyname); }])
+    AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked, procmask; sigemptyset (&blocked); sigaddset (&blocked, SIGCLD); pthread_sigmask (SIG_BLOCK, &blocked, &procmask); grantpt_result = grantpt (fd); pthread_sigmask (SIG_BLOCK, &blocked, &procmask); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, sizeof pty_name, "%s", ptyname); }])
     ;;
 esac
 
@@ -3811,13 +3808,6 @@
     AC_DEFINE(XOS_NEEDS_TIME_H, 1, [Compensate for a bug in Xos.h on
       some systems, where it requires time.h.])
     ;;
-
-  netbsd | openbsd )
-    dnl Greg A. Woods <[email-masked]> says we must include signal.h
-    dnl before syssignal.h is included, to work around interface conflicts
-    dnl that are handled with CPP __RENAME() macro in signal.h.
-    AC_DEFINE(SIGNAL_H_AHB, 1, [Define if AH_BOTTOM should include signal.h.])
-    ;;
 esac

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2012-09-02 17:10:35 +0000
+++ src/ChangeLog	2012-09-03 08:02:33 +0000
@@ -1,3 +1,62 @@
+2012-09-03  Paul Eggert  <[email-masked]>
+
+	Signal-handler cleanup (Bug#12327).
+	Emacs's signal handlers were written in the old 4.2BSD style with
+	sigblock and sigmask and so forth, and this led to some
+	inefficiencies and confusion.  Rewrite these to use
+	pthread_sigmask etc. without copying signal sets around.  Also,
+	get rid of the confusing macros 'SIGNAL_THREAD_CHECK' and
+	'signal', and instead use functions that do not attempt to take
+	over the system name space.  This patch causes Emacs's text
+	segment to shrink by 0.7% on my platform, Fedora 17 x86-64.
+	* alloc.c, emacsgtkfixed.c, nsfns.m, widget.c, xmenu.c:
+	Do not include <signal.h> or "syssignal.h", as these
+	modules do not use signals.
+	* atimer.c, callproc.c, data.c, dispnew.c, emacs.c, floatfns.c:
+	* gtkutil.c, keyboard.c, process.c, sound.c, sysdep.c, term.c, xterm.c:
+	Do not include <signal.h>, as "syssignal.h" does that for us now.
+	* atimer.c (sigmask_atimers): New function.
+	(block_atimers, unblock_atimers): New functions,
+	replacing the old macros BLOCK_ATIMERS and UNBLOCK_ATIMERS.
+	All uses replaced.
+	* conf_post.h [SIGNAL_H_AHB]: Do not include <signal.h>;
+	no longer needed here.
+	* emacs.c (main): Inspect existing signal handler with sigaction,
+	so that there's	no need to block and unblock SIGHUP.
+	* sysdep.c, syssignal.h (SYSSIGNAL_INLINE): New macro.
+	* sysdep.c (struct save_signal): New member 'action', replacing
+	old member 'handler'.
+	(save_signal_handlers, restore_signal_handlers):
+	Use sigaction instead of 'signal' to save and restore.
+	(get_set_sighandler, set_sighandler) [!WINDOWSNT]:
+	New function.  All users of 'signal' modified to use set_sighandler
+	if they're writeonly, and to use sys_signal if they're read+write.
+	(emacs_sigaction_init, forwarded_signal): New functions.
+	(sys_signal): Remove.  All uses replaced by calls to sigaction
+	and emacs_sigaction_init, or by direct calls to 'signal'.
+	(sys_sigmask) [!__GNUC__]: Remove; no longer needed.
+	(sys_sigblock, sys_sigunblock, sys_sigsetmask): Remove;
+	all uses replaced by pthread_sigmask etc. calls.
+	* syssignal.h: Include <signal.h> and <stdbool.h>.
+	Use INLINE_HEADER_BEGIN, INLINE_HEADER_END.
+	(emacs_sigaction_init, forwarded_signal): New decls.
+	(SIGMASKTYPE): Remove.  All uses replaced by its definiens, sigset_t.
+	(SIGEMPTYMASK): Remove; all uses replaced by its definiens, empty_mask.
+	(sigmask, sys_sigmask): Remove; no longer needed.
+	(sigpause): Remove.  All uses replaced by its definiens, sigsuspend.
+	(sigblock, sigunblock, sigfree):
+	(sigsetmask) [!defined sigsetmask]:
+	Remove.  All uses replaced by pthread_sigmask.
+	(signal): Remove.  Its remaining uses (with SIG_DFL and SIG_IGN)
+	no longer need to be replaced, and its typical old uses
+	are now done via emacs_sigaction_init and sigaction.
+	(sys_sigblock, sys_sigunblock, sys_sigsetmask): Remove decls.
+	(sys_sigdel): Remove; unused.
+	(NSIG): Remove a FIXME; the code's fine.  Remove an unnecessary ifdef.
+	(SIGNAL_THREAD_CHECK): Remove.  All uses replaced by calls to
+	forwarded_signal.  This is cleaner, because the caller can now
+	see that the check might immediately return from the caller.
+
 2012-09-02  Paul Eggert  <[email-masked]>
 
 	* emacs.c, eval.c: Use bool for boolean.

=== modified file 'src/alloc.c'
--- src/alloc.c	2012-09-02 16:56:31 +0000
+++ src/alloc.c	2012-09-03 00:06:25 +0000
@@ -26,8 +26,6 @@
 #include <limits.h>		/* For CHAR_BIT.  */
 #include <setjmp.h>
 
-#include <signal.h>
-
 #ifdef HAVE_PTHREAD
 #include <pthread.h>
 #endif
@@ -42,7 +40,6 @@
 #include "keyboard.h"
 #include "frame.h"
 #include "blockinput.h"
-#include "syssignal.h"
 #include "termhooks.h"		/* For struct terminal.  */
 #include <setjmp.h>
 #include <verify.h>

=== modified file 'src/atimer.c'
--- src/atimer.c	2012-08-23 08:27:08 +0000
+++ src/atimer.c	2012-09-03 07:24:03 +0000
@@ -17,7 +17,6 @@
 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
-#include <signal.h>
 #include <stdio.h>
 #include <setjmp.h>
 #include "lisp.h"
@@ -51,8 +50,24 @@
 
 /* Block/unblock SIGALRM.  */
 
-#define BLOCK_ATIMERS   sigblock (sigmask (SIGALRM))
-#define UNBLOCK_ATIMERS sigunblock (sigmask (SIGALRM))
+static void
+sigmask_atimers (int how)
+{
+  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);
+}
 
 /* Function prototypes.  */
 
@@ -111,7 +126,7 @@
   t->fn = fn;
   t->client_data = client_data;
 
-  BLOCK_ATIMERS;
+  block_atimers ();
 
   /* Compute the timer's expiration time.  */
   switch (type)
@@ -132,7 +147,7 @@
 
   /* Insert the timer in the list of active atimers.  */
   schedule_atimer (t);
-  UNBLOCK_ATIMERS;
+  unblock_atimers ();
 
   /* Arrange for a SIGALRM at the time the next atimer is ripe.  */
   set_alarm ();
@@ -148,7 +163,7 @@
 {
   int i;
 
-  BLOCK_ATIMERS;
+  block_atimers ();
 
   for (i = 0; i < 2; ++i)
     {
@@ -175,7 +190,7 @@
 	}
     }
 
-  UNBLOCK_ATIMERS;
+  unblock_atimers ();
 }

@@ -206,7 +221,7 @@
 void
 stop_other_atimers (struct atimer *t)
 {
-  BLOCK_ATIMERS;
+  block_atimers ();
 
   if (t)
     {
@@ -231,7 +246,7 @@
 
   stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
   atimers = t;
-  UNBLOCK_ATIMERS;
+  unblock_atimers ();
 }

@@ -246,7 +261,7 @@
       struct atimer *t = atimers;
       struct atimer *next;
 
-      BLOCK_ATIMERS;
+      block_atimers ();
       atimers = stopped_atimers;
       stopped_atimers = NULL;
 
@@ -257,7 +272,7 @@
 	  t = next;
 	}
 
-      UNBLOCK_ATIMERS;
+      unblock_atimers ();
     }
 }
 
@@ -378,7 +393,8 @@
 alarm_signal_handler (int signo)
 {
 #ifndef SYNC_INPUT
-  SIGNAL_THREAD_CHECK (signo);
+  if (forwarded_signal (signo))
+    return;
 #endif
 
   pending_atimers = 1;
@@ -397,9 +413,9 @@
 {
   if (pending_atimers)
     {
-      BLOCK_ATIMERS;
+      block_atimers ();
       run_timers ();
-      UNBLOCK_ATIMERS;
+      unblock_atimers ();
     }
 }
 
@@ -412,7 +428,9 @@
 {
   if (on)
     {
-      signal (SIGALRM, alarm_signal_handler);
+      struct sigaction action;
+      emacs_sigaction_init (&action, alarm_signal_handler);
+      sigaction (SIGALRM, &action, 0);
       set_alarm ();
     }
   else
@@ -423,8 +441,10 @@
 void
 init_atimer (void)
 {
+  struct sigaction action;
   free_atimers = stopped_atimers = atimers = NULL;
   pending_atimers = 0;
   /* pending_signals is initialized in init_keyboard.*/
-  signal (SIGALRM, alarm_signal_handler);
+  emacs_sigaction_init (&action, alarm_signal_handler);
+  sigaction (SIGALRM, &action, 0);
 }

=== modified file 'src/callproc.c'
--- src/callproc.c	2012-08-25 03:11:12 +0000
+++ src/callproc.c	2012-09-03 06:50:19 +0000
@@ -19,7 +19,6 @@

 #include <config.h>
-#include <signal.h>
 #include <errno.h>
 #include <stdio.h>
 #include <setjmp.h>
@@ -506,9 +505,6 @@
 
     if (fd_output >= 0)
       fd1 = fd_output;
-#if 0  /* Some systems don't have sigblock.  */
-    mask = sigblock (sigmask (SIGCHLD));
-#endif
 
     /* Record that we're about to create a synchronous process.  */
     synch_process_alive = 1;

=== modified file 'src/conf_post.h'
--- src/conf_post.h	2012-08-20 16:48:10 +0000
+++ src/conf_post.h	2012-09-01 21:37:07 +0000
@@ -40,11 +40,6 @@
 #endif
 #endif
 
-#ifdef SIGNAL_H_AHB
-#undef SIGNAL_H_AHB
-#include <signal.h>
-#endif
-
 /* This silences a few compilation warnings on FreeBSD.  */
 #ifdef BSD_SYSTEM_AHB
 #undef BSD_SYSTEM_AHB

=== modified file 'src/data.c'
--- src/data.c	2012-08-27 17:23:48 +0000
+++ src/data.c	2012-09-03 07:24:03 +0000
@@ -19,7 +19,6 @@

 #include <config.h>
-#include <signal.h>
 #include <stdio.h>
 #include <setjmp.h>
 
@@ -3213,15 +3212,16 @@
 static void
 arith_error (int signo)
 {
-  sigsetmask (SIGEMPTYMASK);
-
-  SIGNAL_THREAD_CHECK (signo);
+  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+  if (forwarded_signal (signo))
+    return;
   xsignal0 (Qarith_error);
 }
 
 void
 init_data (void)
 {
+  struct sigaction action;
   /* Don't do this if just dumping out.
      We don't want to call `signal' in this case
      so that we don't have trouble with dumping
@@ -3230,5 +3230,6 @@
   if (!initialized)
     return;
 #endif /* CANNOT_DUMP */
-  signal (SIGFPE, arith_error);
+  emacs_sigaction_init (&action, arith_error);
+  sigaction (SIGFPE, &action, 0);
 }

=== modified file 'src/dispnew.c'
--- src/dispnew.c	2012-09-01 06:38:52 +0000
+++ src/dispnew.c	2012-09-03 07:24:03 +0000
@@ -21,7 +21,6 @@
 
 #define DISPEXTERN_INLINE EXTERN_INLINE
 
-#include <signal.h>
 #include <stdio.h>
 #include <setjmp.h>
 #include <unistd.h>
@@ -5561,8 +5560,11 @@
 
   struct tty_display_info *tty;
 
-  signal (SIGWINCH, window_change_signal);
-  SIGNAL_THREAD_CHECK (signalnum);
+  struct sigaction action;
+  emacs_sigaction_init (&action, window_change_signal);
+  sigaction (SIGWINCH, &action, 0);
+  if (forwarded_signal (signalnum))
+    return;
 
   /* The frame size change obviously applies to a single
      termcap-controlled terminal, but we can't decide which.
@@ -6173,7 +6175,11 @@
 #ifndef CANNOT_DUMP
   if (initialized)
 #endif /* CANNOT_DUMP */
-    signal (SIGWINCH, window_change_signal);
+    {
+      struct sigaction action;
+      emacs_sigaction_init (&action, window_change_signal);
+      sigaction (SIGWINCH, &action, 0);
+    }
 #endif /* SIGWINCH */
 
   /* If running as a daemon, no need to initialize any frames/terminal. */

=== modified file 'src/emacs.c'
--- src/emacs.c	2012-09-02 17:10:35 +0000
+++ src/emacs.c	2012-09-03 07:24:03 +0000
@@ -20,7 +20,6 @@

 #include <config.h>
-#include <signal.h>
 #include <errno.h>
 #include <stdio.h>
 
@@ -297,7 +296,10 @@
 void
 fatal_error_signal (int sig)
 {
-  SIGNAL_THREAD_CHECK (sig);
+  sigset_t unblocked;
+
+  if (forwarded_signal (sig))
+    return;
   fatal_error_code = sig;
   signal (sig, SIG_DFL);
 
@@ -319,7 +321,9 @@
      going to send is probably blocked, so we have to unblock it if we
      want to really receive it.  */
 #ifndef MSDOS
-  sigunblock (sigmask (fatal_error_code));
+  sigemptyset (&unblocked);
+  sigaddset (&unblocked, fatal_error_code);
+  pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
 #endif
 
   kill (getpid (), fatal_error_code);
@@ -331,8 +335,11 @@
 void
 memory_warning_signal (int sig)
 {
-  signal (sig, memory_warning_signal);
-  SIGNAL_THREAD_CHECK (sig);
+  struct sigaction action;
+  emacs_sigaction_init (&action, memory_warning_signal);
+  sigaction (sig, &action, 0);
+  if (forwarded_signal (sig))
+    return;
 
   malloc_warning ("Operating system warns that virtual memory is running low.\n");
 
@@ -687,6 +694,7 @@
   char dname_arg2[80];
 #endif
   char *ch_to_dir;
+  struct sigaction fatal_error_action;
 
 #if GC_MARK_STACK
   stack_base = &dummy;
@@ -1111,6 +1119,7 @@
     }
 
   init_signals ();
+  emacs_sigaction_init (&fatal_error_action, fatal_error_signal);
 
   /* Don't catch SIGHUP if dumping.  */
   if (1
@@ -1119,13 +1128,17 @@
 #endif
       )
     {
-      sigblock (sigmask (SIGHUP));
       /* In --batch mode, don't catch SIGHUP if already ignored.
 	 That makes nohup work.  */
-      if (! noninteractive
-	  || signal (SIGHUP, SIG_IGN) != SIG_IGN)
-	signal (SIGHUP, fatal_error_signal);
-      sigunblock (sigmask (SIGHUP));
+      bool catch_SIGHUP = !noninteractive;
+      if (!catch_SIGHUP)
+	{
+	  struct sigaction old_action;
+	  sigaction (SIGHUP, 0, &old_action);
+	  catch_SIGHUP = old_action.sa_handler != SIG_IGN;
+	}
+      if (catch_SIGHUP)
+	sigaction (SIGHUP, &fatal_error_action, 0);
     }
 
   if (
@@ -1139,9 +1152,9 @@
       /* Don't catch these signals in batch mode if dumping.
 	 On some machines, this sets static data that would make
 	 signal fail to work right when the dumped Emacs is run.  */
-      signal (SIGQUIT, fatal_error_signal);
-      signal (SIGILL, fatal_error_signal);
-      signal (SIGTRAP, fatal_error_signal);
+      sigaction (SIGQUIT, &fatal_error_action, 0);
+      sigaction (SIGILL, &fatal_error_action, 0);
+      sigaction (SIGTRAP, &fatal_error_action, 0);
 #ifdef SIGUSR1
       add_user_signal (SIGUSR1, "sigusr1");
 #endif
@@ -1149,68 +1162,73 @@
       add_user_signal (SIGUSR2, "sigusr2");
 #endif
 #ifdef SIGABRT
-      signal (SIGABRT, fatal_error_signal);
+      sigaction (SIGABRT, &fatal_error_action, 0);
 #endif
 #ifdef SIGHWE
-      signal (SIGHWE, fatal_error_signal);
+      sigaction (SIGHWE, &fatal_error_action, 0);
 #endif
 #ifdef SIGPRE
-      signal (SIGPRE, fatal_error_signal);
+      sigaction (SIGPRE, &fatal_error_action, 0);
 #endif
 #ifdef SIGORE
-      signal (SIGORE, fatal_error_signal);
+      sigaction (SIGORE, &fatal_error_action, 0);
 #endif
 #ifdef SIGUME
-      signal (SIGUME, fatal_error_signal);
+      sigaction (SIGUME, &fatal_error_action, 0);
 #endif
 #ifdef SIGDLK
-      signal (SIGDLK, fatal_error_signal);
+      sigaction (SIGDLK, &fatal_error_action, 0);
 #endif
 #ifdef SIGCPULIM
-      signal (SIGCPULIM, fatal_error_signal);
+      sigaction (SIGCPULIM, &fatal_error_action, 0);
 #endif
 #ifdef SIGIOT
       /* This is missing on some systems - OS/2, for example.  */
-      signal (SIGIOT, fatal_error_signal);
+      sigaction (SIGIOT, &fatal_error_action, 0);
 #endif
 #ifdef SIGEMT
-      signal (SIGEMT, fatal_error_signal);
+      sigaction (SIGEMT, &fatal_error_action, 0);
 #endif
-      signal (SIGFPE, fatal_error_signal);
+      sigaction (SIGFPE, &fatal_error_action, 0);
 #ifdef SIGBUS
-      signal (SIGBUS, fatal_error_signal);
+      sigaction (SIGBUS, &fatal_error_action, 0);
 #endif
-      signal (SIGSEGV, fatal_error_signal);
+      sigaction (SIGSEGV, &fatal_error_action, 0);
 #ifdef SIGSYS
-      signal (SIGSYS, fatal_error_signal);
+      sigaction (SIGSYS, &fatal_error_action, 0);
 #endif
       /*  May need special treatment on MS-Windows. See
           http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01062.html
           Please update the doc of kill-emacs, kill-emacs-hook, and
           NEWS if you change this.
       */
-      if (noninteractive) signal (SIGINT, fatal_error_signal);
-      signal (SIGTERM, fatal_error_signal);
+      if (noninteractive)
+	sigaction (SIGINT, &fatal_error_action, 0);
+      sigaction (SIGTERM, &fatal_error_action, 0);
 #ifdef SIGXCPU
-      signal (SIGXCPU, fatal_error_signal);
+      sigaction (SIGXCPU, &fatal_error_action, 0);
 #endif
 #ifdef SIGXFSZ
-      signal (SIGXFSZ, fatal_error_signal);
+      sigaction (SIGXFSZ, &fatal_error_action, 0);
 #endif /* SIGXFSZ */
 
 #ifdef SIGDANGER
       /* This just means available memory is getting low.  */
-      signal (SIGDANGER, memory_warning_signal);
+      {
+	struct sigaction action;
+	emacs_sigaction_init (&action, memory_warning_signal);
+	sigaction (SIGDANGER, &action, 0);
+      }
 #endif
 
 #ifdef AIX
 /* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU.  */
-      signal (SIGXCPU, fatal_error_signal);
-      signal (SIGIOINT, fatal_error_signal);
-      signal (SIGGRANT, fatal_error_signal);
-      signal (SIGRETRACT, fatal_error_signal);
-      signal (SIGSOUND, fatal_error_signal);
-      signal (SIGMSG, fatal_error_signal);
+      sigaction (SIGXCPU, &fatal_error_action, 0);
+      sigaction (SIGIOINT, &fatal_error_action, 0);
+      sigaction (SIGGRANT, &fatal_error_action, 0);
+      sigaction (SIGRETRACT, &fatal_error_action, 0);
+      sigaction (SIGSOUND, &fatal_error_action, 0);
+      sigaction (SIGMSG, &fatal_error_action, 0);
 #endif /* AIX */
     }

=== modified file 'src/emacsgtkfixed.c'
--- src/emacsgtkfixed.c	2012-04-23 07:34:29 +0000
+++ src/emacsgtkfixed.c	2012-09-01 21:37:07 +0000
@@ -21,7 +21,6 @@
 #include <config.h>
 
 #include "emacsgtkfixed.h"
-#include <signal.h>
 #include <stdio.h>
 #include <setjmp.h>
 #include "lisp.h"

=== modified file 'src/floatfns.c'
--- src/floatfns.c	2012-07-17 02:56:00 +0000
+++ src/floatfns.c	2012-09-03 07:24:03 +0000
@@ -48,7 +48,6 @@
  */
 
 #include <config.h>
-#include <signal.h>
 #include <setjmp.h>
 #include "lisp.h"
 #include "syssignal.h"
@@ -955,13 +954,18 @@
     fatal_error_signal (signo);
 
 #ifdef BSD_SYSTEM
-  sigsetmask (SIGEMPTYMASK);
+  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
 #else
   /* Must reestablish handler each time it is called.  */
-  signal (SIGILL, float_error);
+  {
+    struct sigaction action;
+    emacs_sigaction_init (&action, float_error);
+    sigaction (SIGILL, &action, 0);
+  }
 #endif /* BSD_SYSTEM */
 
-  SIGNAL_THREAD_CHECK (signo);
+  if (forwarded_signal (signo))
+    return;
   in_float = 0;
 
   xsignal1 (Qarith_error, float_error_arg);
@@ -1007,7 +1011,9 @@
 init_floatfns (void)
 {
 #ifdef FLOAT_CATCH_SIGILL
-  signal (SIGILL, float_error);
+  struct sigaction action;
+  emacs_sigaction_init (&action, float_error);
+  sigaction (SIGILL, &action, 0);
 #endif
   in_float = 0;
 }

=== modified file 'src/gtkutil.c'
--- src/gtkutil.c	2012-09-02 16:56:31 +0000
+++ src/gtkutil.c	2012-09-03 06:50:19 +0000
@@ -21,7 +21,6 @@
 
 #ifdef USE_GTK
 #include <float.h>
-#include <signal.h>
 #include <stdio.h>
 #include <setjmp.h>
 
@@ -1979,7 +1978,10 @@
   /* I really don't know why this is needed, but without this the GLIBC add on
      library linuxthreads hangs when the Gnome file chooser backend creates
      threads.  */
-  sigblock (sigmask (__SIGRTMIN));
+  sigset_t blocked;
+  sigemptyset (&blocked);
+  sigaddset (&blocked, __SIGRTMIN);
+  pthread_sigmask (SIG_BLOCK, &blocked, 0);
 #endif /* HAVE_PTHREAD */
 
 #ifdef HAVE_GTK_FILE_SELECTION_NEW
@@ -2001,7 +2003,7 @@
   filesel_done = xg_dialog_run (f, w);
 
 #if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
-  sigunblock (sigmask (__SIGRTMIN));
+  pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
 #endif
 
   if (filesel_done == GTK_RESPONSE_OK)
@@ -2056,7 +2058,10 @@
   Lisp_Object font = Qnil;
 
 #if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
-  sigblock (sigmask (__SIGRTMIN));
+  sigset_t blocked;
+  sigemptyset (&blocked);
+  sigaddset (&blocked, __SIGRTMIN);
+  pthread_sigmask (SIG_BLOCK, &blocked, 0);
 #endif /* HAVE_PTHREAD */
 
   w = gtk_font_chooser_dialog_new
@@ -2085,7 +2090,7 @@
   done = xg_dialog_run (f, w);
 
 #if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
-  sigunblock (sigmask (__SIGRTMIN));
+  pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
 #endif
 
   if (done == GTK_RESPONSE_OK)

=== modified file 'src/keyboard.c'
--- src/keyboard.c	2012-09-02 16:56:31 +0000
+++ src/keyboard.c	2012-09-03 07:24:03 +0000
@@ -21,7 +21,6 @@
 
 #define KEYBOARD_INLINE EXTERN_INLINE
 
-#include <signal.h>
 #include <stdio.h>
 #include <setjmp.h>
 #include "lisp.h"
@@ -3681,7 +3680,7 @@
       if (immediate_quit && NILP (Vinhibit_quit))
 	{
 	  immediate_quit = 0;
-	  sigfree ();
+	  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
 	  QUIT;
 	}
     }
@@ -3833,7 +3832,11 @@
       unhold_keyboard_input ();
 #ifdef SIGIO
       if (!noninteractive)
-        signal (SIGIO, input_available_signal);
+	{
+	  struct sigaction action;
+	  emacs_sigaction_init (&action, input_available_signal);
+	  sigaction (SIGIO, &action, 0);
+	}
 #endif /* SIGIO */
       start_polling ();
     }
@@ -6781,10 +6784,12 @@
 #ifdef SIGIO
   if (interrupt_input)
     {
-      SIGMASKTYPE mask;
-      mask = sigblock (sigmask (SIGIO));
+      sigset_t blocked, procmask;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, SIGIO);
+      pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
       read_avail_input (expected);
-      sigsetmask (mask);
+      pthread_sigmask (SIG_SETMASK, &procmask, 0);
     }
   else
 #ifdef POLL_FOR_INPUT
@@ -6793,10 +6798,12 @@
      it's always set.  */
   if (!interrupt_input && poll_suppress_count == 0)
     {
-      SIGMASKTYPE mask;
-      mask = sigblock (sigmask (SIGALRM));
+      sigset_t blocked, procmask;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, SIGALRM);
+      pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
       read_avail_input (expected);
-      sigsetmask (mask);
+      pthread_sigmask (SIG_SETMASK, &procmask, 0);
     }
   else
 #endif
@@ -6832,10 +6839,12 @@
 #ifdef SIGIO
   if (interrupt_input)
     {
-      SIGMASKTYPE mask;
-      mask = sigblock (sigmask (SIGIO));
+      sigset_t blocked, procmask;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, SIGIO);
+      pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
       kbd_buffer_store_event (&event);
-      sigsetmask (mask);
+      pthread_sigmask (SIG_SETMASK, &procmask, 0);
     }
   else
 #endif
@@ -7240,7 +7249,8 @@
 {
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
-  SIGNAL_THREAD_CHECK (signo);
+  if (forwarded_signal (signo))
+    return;
 
 #ifdef SYNC_INPUT
   interrupt_input_pending = 1;
@@ -7296,6 +7306,7 @@
 void
 add_user_signal (int sig, const char *name)
 {
+  struct sigaction action;
   struct user_signal_info *p;
 
   for (p = user_signals; p; p = p->next)
@@ -7310,7 +7321,8 @@
   p->next = user_signals;
   user_signals = p;
 
-  signal (sig, handle_user_signal);
+  emacs_sigaction_init (&action, handle_user_signal);
+  sigaction (sig, &action, 0);
 }
 
 static void
@@ -7320,7 +7332,8 @@
   struct user_signal_info *p;
   const char *special_event_name = NULL;
 
-  SIGNAL_THREAD_CHECK (sig);
+  if (forwarded_signal (sig))
+    return;
 
   if (SYMBOLP (Vdebug_on_event))
     special_event_name = SSDATA (SYMBOL_NAME (Vdebug_on_event));
@@ -7381,7 +7394,7 @@
   for (p = user_signals; p; p = p->next)
     if (p->npending > 0)
       {
-	SIGMASKTYPE mask;
+	sigset_t blocked, procmask;
 
 	if (nstored == 0)
 	  {
@@ -7391,7 +7404,10 @@
 	  }
 	nstored += p->npending;
 
-	mask = sigblock (sigmask (p->sig));
+	sigemptyset (&blocked);
+	sigaddset (&blocked, p->sig);
+	pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
+
 	do
 	  {
 	    buf.code = p->sig;
@@ -7399,7 +7415,8 @@
 	    p->npending--;
 	  }
 	while (p->npending > 0);
-	sigsetmask (mask);
+
+	pthread_sigmask (SIG_SETMASK, &procmask, 0);
       }
 
   return nstored;
@@ -10783,7 +10800,8 @@
   int old_errno = errno;
   struct terminal *terminal;
 
-  SIGNAL_THREAD_CHECK (signalnum);
+  if (forwarded_signal (signalnum))
+    return;
 
   /* See if we have an active terminal on our controlling tty.  */
   terminal = get_named_tty ("/dev/tty");
@@ -10840,7 +10858,10 @@
       /* If SIGINT isn't blocked, don't let us be interrupted by
 	 another SIGINT, it might be harmful due to non-reentrancy
 	 in I/O functions.  */
-      sigblock (sigmask (SIGINT));
+      sigset_t blocked;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, SIGINT);
+      pthread_sigmask (SIG_BLOCK, &blocked, 0);
 
       fflush (stdout);
       reset_all_sys_modes ();
@@ -10911,7 +10932,7 @@
 #endif /* not MSDOS */
       fflush (stdout);
       init_all_sys_modes ();
-      sigfree ();
+      pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
     }
   else
     {
@@ -10924,7 +10945,7 @@
 	  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
 	  immediate_quit = 0;
-          sigfree ();
+	  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
 	  saved = gl_state;
 	  GCPRO4 (saved.object, saved.global_code,
 		  saved.current_syntax_table, saved.old_prop);
@@ -10969,7 +10990,7 @@
   if (!from_signal && EQ (Vquit_flag, Qkill_emacs))
     Fkill_emacs (Qnil);
 
-  sigfree ();
+  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
   /* Prevent another signal from doing this before we finish.  */
   clear_waiting_for_input ();
   input_pending = 0;
@@ -11404,17 +11425,23 @@
          SIGINT.  There is special code in interrupt_signal to exit
          Emacs on SIGINT when there are no termcap frames on the
          controlling terminal.  */
-      signal (SIGINT, interrupt_signal);
+      struct sigaction action;
+      emacs_sigaction_init (&action, interrupt_signal);
+      sigaction (SIGINT, &action, 0);
 #ifndef DOS_NT
       /* For systems with SysV TERMIO, C-g is set up for both SIGINT and
 	 SIGQUIT and we can't tell which one it will give us.  */
-      signal (SIGQUIT, interrupt_signal);
+      sigaction (SIGQUIT, &action, 0);
 #endif /* not DOS_NT */
     }
 /* Note SIGIO has been undef'd if FIONREAD is missing.  */
 #ifdef SIGIO
   if (!noninteractive)
-    signal (SIGIO, input_available_signal);
+    {
+      struct sigaction action;
+      emacs_sigaction_init (&action, input_available_signal);
+      sigaction (SIGIO, &action, 0);
+    }
 #endif /* SIGIO */
 
 /* Use interrupt input by default, if it works and noninterrupt input
@@ -11426,7 +11453,7 @@
   interrupt_input = 0;
 #endif
 
-  sigfree ();
+  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
   dribble = 0;
 
   if (keyboard_init_hook)

=== modified file 'src/nsfns.m'
--- src/nsfns.m	2012-08-17 23:38:43 +0000
+++ src/nsfns.m	2012-09-01 21:37:07 +0000
@@ -30,7 +30,6 @@
    interpretation of even the system includes. */
 #include <config.h>
 
-#include <signal.h>
 #include <math.h>
 #include <setjmp.h>
 #include <c-strcase.h>

=== modified file 'src/process.c'
--- src/process.c	2012-09-02 17:10:35 +0000
+++ src/process.c	2012-09-03 07:24:03 +0000
@@ -23,7 +23,6 @@
 
 #define PROCESS_INLINE EXTERN_INLINE
 
-#include <signal.h>
 #include <stdio.h>
 #include <errno.h>
 #include <setjmp.h>
@@ -1603,8 +1602,7 @@
 #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
   int wait_child_setup[2];
 #endif
-  sigset_t procmask;
-  sigset_t blocked;
+  sigset_t blocked, procmask;
   struct sigaction sigint_action;
   struct sigaction sigquit_action;
   struct sigaction sigpipe_action;
@@ -1756,12 +1754,6 @@
 	int xforkin = forkin;
 	int xforkout = forkout;
 
-#if 0 /* This was probably a mistake--it duplicates code later on,
-	 but fails to handle all the cases.  */
-	/* Make sure SIGCHLD is not blocked in the child.  */
-	sigsetmask (SIGEMPTYMASK);
-#endif
-
 	/* Make the pty be the controlling terminal of the process.  */
 #ifdef HAVE_PTYS
 	/* First, disconnect its current controlling terminal.  */
@@ -5429,8 +5421,12 @@
 static void
 send_process_trap (int ignore)
 {
-  SIGNAL_THREAD_CHECK (SIGPIPE);
-  sigunblock (sigmask (SIGPIPE));
+  sigset_t unblocked;
+  if (forwarded_signal (SIGPIPE))
+    return;
+  sigemptyset (&unblocked);
+  sigaddset (&unblocked, SIGPIPE);
+  pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
   longjmp (send_process_frame, 1);
 }
 
@@ -5524,7 +5520,7 @@
   struct Lisp_Process *p = XPROCESS (proc);
   ssize_t rv;
   struct coding_system *coding;
-  void (*volatile old_sigpipe) (int);
+  struct sigaction old_sigpipe_action;
 
   if (p->raw_status_new)
     update_status (p);
@@ -5663,7 +5659,9 @@
 	      /* Send this batch, using one or more write calls.  */
 	      ptrdiff_t written = 0;
 	      int outfd = p->outfd;
-	      old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap);
+	      struct sigaction action;
+	      emacs_sigaction_init (&action, send_process_trap);
+	      sigaction (SIGPIPE, &action, &old_sigpipe_action);
 #ifdef DATAGRAM_SOCKETS
 	      if (DATAGRAM_CHAN_P (outfd))
 		{
@@ -5674,7 +5672,7 @@
 		    written = rv;
 		  else if (errno == EMSGSIZE)
 		    {
-		      signal (SIGPIPE, old_sigpipe);
+		      sigaction (SIGPIPE, &old_sigpipe_action, 0);
 		      report_file_error ("sending datagram",
 					 Fcons (proc, Qnil));
 		    }
@@ -5699,7 +5697,7 @@
 		    }
 #endif
 		}
-	      signal (SIGPIPE, old_sigpipe);
+	      sigaction (SIGPIPE, &old_sigpipe_action, 0);
 
 	      if (rv < 0)
 		{
@@ -5759,7 +5757,7 @@
     }
   else
     {
-      signal (SIGPIPE, old_sigpipe);
+      sigaction (SIGPIPE, &old_sigpipe_action, 0);
       proc = process_sent_to;
       p = XPROCESS (proc);
       p->raw_status_new = 0;
@@ -6404,7 +6402,8 @@
   Lisp_Object proc;
   struct Lisp_Process *p;
 
-  SIGNAL_THREAD_CHECK (signo);
+  if (forwarded_signal (signo))
+    return;
 
   while (1)
     {
@@ -7387,7 +7386,11 @@
 #ifndef CANNOT_DUMP
   if (! noninteractive || initialized)
 #endif
-    signal (SIGCHLD, sigchld_handler);
+    {
+      struct sigaction action;
+      emacs_sigaction_init (&action, sigchld_handler);
+      sigaction (SIGCHLD, &action, 0);
+    }
 #endif
 
   FD_ZERO (&input_wait_mask);

=== modified file 'src/sound.c'
--- src/sound.c	2012-07-29 08:18:29 +0000
+++ src/sound.c	2012-09-03 06:50:19 +0000
@@ -48,7 +48,6 @@
 #include "lisp.h"
 #include "dispextern.h"
 #include "atimer.h"
-#include <signal.h>
 #include "syssignal.h"
 /* END: Common Includes */
 
@@ -316,7 +315,12 @@
 
   turn_on_atimers (1);
 #ifdef SIGIO
-  sigunblock (sigmask (SIGIO));
+  {
+    sigset_t unblocked;
+    sigemptyset (&unblocked);
+    sigaddset (&unblocked, SIGIO);
+    pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
+  }
 #endif
   if (saved_errno != 0)
     error ("%s: %s", msg, strerror (saved_errno));
@@ -728,6 +732,9 @@
 vox_configure (struct sound_device *sd)
 {
   int val;
+#ifdef SIGIO
+  sigset_t blocked;
+#endif
 
   eassert (sd->fd >= 0);
 
@@ -736,7 +743,9 @@
      troubles.  */
   turn_on_atimers (0);
 #ifdef SIGIO
-  sigblock (sigmask (SIGIO));
+  sigemptyset (&blocked);
+  sigaddset (&blocked, SIGIO);
+  pthread_sigmask (SIG_BLOCK, &blocked, 0);
 #endif
 
   val = sd->format;
@@ -770,7 +779,7 @@
 
   turn_on_atimers (1);
 #ifdef SIGIO
-  sigunblock (sigmask (SIGIO));
+  pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
 #endif
 }
 
@@ -786,7 +795,10 @@
 	 be interrupted by a signal.  Block the ones we know to cause
 	 troubles.  */
 #ifdef SIGIO
-      sigblock (sigmask (SIGIO));
+      sigset_t blocked;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, SIGIO);
+      pthread_sigmask (SIG_BLOCK, &blocked, 0);
 #endif
       turn_on_atimers (0);
 
@@ -795,7 +807,7 @@
 
       turn_on_atimers (1);
 #ifdef SIGIO
-      sigunblock (sigmask (SIGIO));
+      pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
 #endif
 
       /* Close the device.  */

=== modified file 'src/sysdep.c'
--- src/sysdep.c	2012-09-01 01:13:50 +0000
+++ src/sysdep.c	2012-09-03 07:38:38 +0000
@@ -19,9 +19,9 @@
 
 #include <config.h>
 
+#define SYSSIGNAL_INLINE EXTERN_INLINE
 #define SYSTIME_INLINE EXTERN_INLINE
 
-#include <signal.h>
 #include <stdio.h>
 #include <setjmp.h>
 #ifdef HAVE_PWD_H
@@ -302,27 +302,34 @@
 	 termination of subprocesses, perhaps involving a kernel bug too,
 	 but no idea what it is.  Just as a hunch we signal SIGCHLD to see
 	 if that causes the problem to go away or get worse.  */
-      sigsetmask (sigmask (SIGCHLD));
+      sigset_t sigchild_mask;
+      sigemptyset (&sigchild_mask);
+      sigaddset (&sigchild_mask, SIGCHLD);
+      pthread_sigmask (SIG_SETMASK, &sigchild_mask, 0);
+
       if (0 > kill (pid, 0))
 	{
-	  sigsetmask (SIGEMPTYMASK);
+	  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
 	  kill (getpid (), SIGCHLD);
 	  break;
 	}
       if (wait_debugging)
 	sleep (1);
       else
-	sigpause (SIGEMPTYMASK);
+	sigsuspend (&empty_mask);
 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
 #ifdef WINDOWSNT
       wait (0);
       break;
 #else /* not WINDOWSNT */
-      sigblock (sigmask (SIGCHLD));
+      sigset_t blocked;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, SIGCHLD);
+      pthread_sigmask (SIG_BLOCK, &blocked, 0);
       errno = 0;
       if (kill (pid, 0) == -1 && errno == ESRCH)
 	{
-	  sigunblock (sigmask (SIGCHLD));
+	  pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
 	  break;
 	}
 
@@ -456,11 +463,11 @@
 #endif	/* not MSDOS */
 
 
-/* Record a signal code and the handler for it.  */
+/* Record a signal code and the action for it.  */
 struct save_signal
 {
   int code;
-  void (*handler) (int);
+  struct sigaction action;
 };
 
 static void save_signal_handlers (struct save_signal *);
@@ -618,8 +625,9 @@
 {
   while (saved_handlers->code)
     {
-      saved_handlers->handler
-        = (void (*) (int)) signal (saved_handlers->code, SIG_IGN);
+      struct sigaction action;
+      emacs_sigaction_init (&action, SIG_IGN);
+      sigaction (saved_handlers->code, &action, &saved_handlers->action);
       saved_handlers++;
     }
 }
@@ -629,7 +637,7 @@
 {
   while (saved_handlers->code)
     {
-      signal (saved_handlers->code, saved_handlers->handler);
+      sigaction (saved_handlers->code, &saved_handlers->action, 0);
       saved_handlers++;
     }
 }
@@ -686,13 +694,17 @@
 void
 request_sigio (void)
 {
+  sigset_t unblocked;
+
   if (noninteractive)
     return;
 
+  sigemptyset (&unblocked);
 #ifdef SIGWINCH
-  sigunblock (sigmask (SIGWINCH));
+  sigaddset (&unblocked, SIGWINCH);
 #endif
-  sigunblock (sigmask (SIGIO));
+  sigaddset (&unblocked, SIGIO);
+  pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
 
   interrupts_deferred = 0;
 }
@@ -700,6 +712,8 @@
 void
 unrequest_sigio (void)
 {
+  sigset_t blocked;
+
   if (noninteractive)
     return;
 
@@ -708,10 +722,12 @@
     return;
 #endif
 
+  sigemptyset (&blocked);
 #ifdef SIGWINCH
-  sigblock (sigmask (SIGWINCH));
+  sigaddset (&blocked, SIGWINCH);
 #endif
-  sigblock (sigmask (SIGIO));
+  sigaddset (&blocked, SIGIO);
+  pthread_sigmask (SIG_BLOCK, &blocked, 0);
   interrupts_deferred = 1;
 }
 
@@ -1470,20 +1486,16 @@
   }
 }
 
-/* POSIX signals support - DJB */
-/* Anyone with POSIX signals should have ANSI C declarations */
-
 sigset_t empty_mask;
 
-#ifndef WINDOWSNT
-
-signal_handler_t
-sys_signal (int signal_number, signal_handler_t action)
+/* Store into *ACTION a signal action suitable for Emacs, with handler
+   HANDLER.  */
+void
+emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
 {
-  struct sigaction new_action, old_action;
-  sigemptyset (&new_action.sa_mask);
-  new_action.sa_handler = action;
-  new_action.sa_flags = 0;
+  sigemptyset (&action->sa_mask);
+  action->sa_handler = handler;
+  action->sa_flags = 0;
 #if defined (SA_RESTART)
   /* Emacs mostly works better with restartable system services. If this
      flag exists, we probably want to turn it on here.
@@ -1500,57 +1512,31 @@
 # if defined (BROKEN_SA_RESTART) || defined (SYNC_INPUT)
   if (noninteractive)
 # endif
-    new_action.sa_flags = SA_RESTART;
-#endif
-  sigaction (signal_number, &new_action, &old_action);
-  return (old_action.sa_handler);
-}
-
-#endif	/* WINDOWSNT */
-
-#ifndef __GNUC__
-/* If we're compiling with GCC, we don't need this function, since it
-   can be written as a macro.  */
-sigset_t
-sys_sigmask (int sig)
-{
-  sigset_t mask;
-  sigemptyset (&mask);
-  sigaddset (&mask, sig);
-  return mask;
-}
-#endif
-
-/* I'd like to have these guys return pointers to the mask storage in here,
-   but there'd be trouble if the code was saving multiple masks.  I'll be
-   safe and pass the structure.  It normally won't be more than 2 bytes
-   anyhow. - DJB */
-
-sigset_t
-sys_sigblock (sigset_t new_mask)
-{
-  sigset_t old_mask;
-  pthread_sigmask (SIG_BLOCK, &new_mask, &old_mask);
-  return (old_mask);
-}
-
-sigset_t
-sys_sigunblock (sigset_t new_mask)
-{
-  sigset_t old_mask;
-  pthread_sigmask (SIG_UNBLOCK, &new_mask, &old_mask);
-  return (old_mask);
-}
-
-sigset_t
-sys_sigsetmask (sigset_t new_mask)
-{
-  sigset_t old_mask;
-  pthread_sigmask (SIG_SETMASK, &new_mask, &old_mask);
-  return (old_mask);
-}
-
-
+    action->sa_flags = SA_RESTART;
+#endif
+}
+
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+/* POSIX says any thread can receive the signal.  On GNU/Linux that is
+   not true, but for other systems (FreeBSD at least) it is.  So
+   direct the signal to the correct thread and block it from this thread.  */
+bool
+forwarded_signal (int signo)
+{
+  if (pthread_equal (pthread_self (), main_thread))
+    return 0;
+  else
+    {
+      sigset_t blocked;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, signo);
+      pthread_sigmask (SIG_BLOCK, &blocked, 0);
+      pthread_kill (main_thread, signo);
+      return 1;
+    }
+}
+#endif
+
 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
 static char *my_sys_siglist[NSIG];
 # ifdef sys_siglist

=== modified file 'src/syssignal.h'
--- src/syssignal.h	2012-07-13 01:19:06 +0000
+++ src/syssignal.h	2012-09-03 07:38:38 +0000
@@ -17,6 +17,9 @@
 You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
+#include <signal.h>
+#include <stdbool.h>
+
 extern void init_signals (void);
 
 #ifdef HAVE_PTHREAD
@@ -26,63 +29,21 @@
 #define FORWARD_SIGNAL_TO_MAIN_THREAD
 #endif
 
-/* Don't #include <signal.h>.  That header should always be #included
-   before "config.h", because some configuration files (like s/hpux.h)
-   indicate that SIGIO doesn't work by #undef-ing SIGIO.  If this file
-   #includes <signal.h>, then that will re-#define SIGIO and confuse
-   things.  */
-/* XXX This is not correct anymore, there is a BROKEN_SIGIO macro. */
-
-#define SIGMASKTYPE sigset_t
-
-#define SIGEMPTYMASK (empty_mask)
+INLINE_HEADER_BEGIN
+#ifndef SYSSIGNAL_INLINE
+# define SYSSIGNAL_INLINE INLINE
+#endif
+
 extern sigset_t empty_mask;
 
-/* POSIX pretty much destroys any possibility of writing sigmask as a
-   macro in standard C.  We always define our own version because the
-   predefined macro in Glibc 2.1 is only provided for compatibility for old
-   programs that use int as signal mask type.  */
-#undef sigmask
-#ifdef __GNUC__
-#define sigmask(SIG) 				\
-  ({						\
-    sigset_t _mask;				\
-    sigemptyset (&_mask);			\
-    sigaddset (&_mask, SIG);			\
-    _mask;					\
-  })
-#else /* ! defined (__GNUC__) */
-extern sigset_t sys_sigmask ();
-#define sigmask(SIG) (sys_sigmask (SIG))
-#endif /* ! defined (__GNUC__) */
-
-#undef sigpause
-#define sigpause(MASK)    sigsuspend (&(MASK))
-
-#define sigblock(SIG)    sys_sigblock (SIG)
-#define sigunblock(SIG)  sys_sigunblock (SIG)
-#ifndef sigsetmask
-#define sigsetmask(SIG)  sys_sigsetmask (SIG)
-#endif
-#undef signal
-#define signal(SIG,ACT)      sys_signal(SIG,ACT)
-
-/* Whether this is what all systems want or not, this is what
-   appears to be assumed in the source, for example data.c:arith_error.  */
 typedef void (*signal_handler_t) (int);
 
-signal_handler_t sys_signal (int signal_number, signal_handler_t action);
-sigset_t sys_sigblock   (sigset_t new_mask);
-sigset_t sys_sigunblock (sigset_t new_mask);
-sigset_t sys_sigsetmask (sigset_t new_mask);
+extern void emacs_sigaction_init (struct sigaction *, signal_handler_t);
+
 #if ! (defined TIOCNOTTY || defined USG5 || defined CYGWIN)
 _Noreturn void croak (char *);
 #endif
 
-#define sys_sigdel(MASK,SIG) sigdelset (&MASK,SIG)
-
-#define sigfree() sigsetmask (SIGEMPTYMASK)
-
 #if defined (SIGIO) && defined (BROKEN_SIGIO)
 # undef SIGIO
 #endif
@@ -97,12 +58,8 @@
 #undef SIGPTY
 #endif
 
-
-/* FIXME?  Emacs only defines NSIG_MINIMUM on some platforms?  */
 #if NSIG < NSIG_MINIMUM
-# ifdef NSIG
-#  undef NSIG
-# endif
+# undef NSIG
 # define NSIG NSIG_MINIMUM
 #endif
 
@@ -133,24 +90,9 @@
 
 #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
 extern pthread_t main_thread;
-#define SIGNAL_THREAD_CHECK(signo)                                      \
-  do {                                                                  \
-    if (!pthread_equal (pthread_self (), main_thread))			\
-      {                                                                 \
-        /* POSIX says any thread can receive the signal.  On GNU/Linux  \
-           that is not true, but for other systems (FreeBSD at least)   \
-           it is.  So direct the signal to the correct thread and block \
-           it from this thread.  */                                     \
-        sigset_t new_mask;                                              \
-                                                                        \
-        sigemptyset (&new_mask);                                        \
-        sigaddset (&new_mask, signo);                                   \
-        pthread_sigmask (SIG_BLOCK, &new_mask, 0);                      \
-        pthread_kill (main_thread, signo);                              \
-        return;                                                         \
-      }                                                                 \
-   } while (0)
+extern bool forwarded_signal (int);
+#else
+SYSSIGNAL_INLINE bool forwarded_signal (int signo) { return 0; }
+#endif
 
-#else /* not FORWARD_SIGNAL_TO_MAIN_THREAD */
-#define SIGNAL_THREAD_CHECK(signo)
-#endif /* not FORWARD_SIGNAL_TO_MAIN_THREAD */
+INLINE_HEADER_END

=== modified file 'src/term.c'
--- src/term.c	2012-08-31 10:53:19 +0000
+++ src/term.c	2012-09-03 06:50:19 +0000
@@ -25,7 +25,6 @@
 #include <sys/file.h>
 #include <sys/time.h>
 #include <unistd.h>
-#include <signal.h>
 #include <setjmp.h>
 
 #include "lisp.h"
@@ -2932,7 +2931,10 @@
       no_controlling_tty = 1;
 #else
 #ifdef TIOCNOTTY                /* Try BSD ioctls. */
-      sigblock (sigmask (SIGTTOU));
+      sigset_t blocked;
+      sigemptyset (&blocked);
+      sigaddset (&blocked, SIGTTOU);
+      pthread_sigmask (SIG_BLOCK, &blocked, 0);
       fd = emacs_open (DEV_TTY, O_RDWR, 0);
       if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
         {
@@ -2940,7 +2942,7 @@
         }
       if (fd != -1)
         emacs_close (fd);
-      sigunblock (sigmask (SIGTTOU));
+      pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
 #else
       /* Unknown system. */
       croak ();
@@ -2971,6 +2973,7 @@
   struct tty_display_info *tty = NULL;
   struct terminal *terminal = NULL;
   int ctty = 0;                 /* 1 if asked to open controlling tty. */
+  sigset_t blocked;
 
   if (!terminal_type)
     maybe_fatal (must_succeed, 0,
@@ -3074,9 +3077,11 @@
 
   /* On some systems, tgetent tries to access the controlling
      terminal. */
-  sigblock (sigmask (SIGTTOU));
+  sigemptyset (&blocked);
+  sigaddset (&blocked, SIGTTOU);
+  pthread_sigmask (SIG_BLOCK, &blocked, 0);
   status = tgetent (tty->termcap_term_buffer, terminal_type);
-  sigunblock (sigmask (SIGTTOU));
+  pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
 
   if (status < 0)
     {

=== modified file 'src/widget.c'
--- src/widget.c	2012-09-02 16:56:31 +0000
+++ src/widget.c	2012-09-03 00:06:25 +0000
@@ -50,9 +50,6 @@
 #include <X11/ShellP.h>
 #include "../lwlib/lwlib.h"
 
-#include <signal.h>
-#include "syssignal.h"
-
 #include "character.h"
 #include "font.h"

=== modified file 'src/xmenu.c'
--- src/xmenu.c	2012-08-17 21:52:15 +0000
+++ src/xmenu.c	2012-09-01 21:37:07 +0000
@@ -32,11 +32,6 @@
 
 #include <config.h>
 
-#if 0  /* Why was this included?  And without syssignal.h?  */
-/* On 4.3 this loses if it comes after xterm.h.  */
-#include <signal.h>
-#endif
-
 #include <stdio.h>
 #include <setjmp.h>

=== modified file 'src/xterm.c'
--- src/xterm.c	2012-09-02 17:10:35 +0000
+++ src/xterm.c	2012-09-03 07:24:03 +0000
@@ -21,7 +21,6 @@
 /* Xt features made by Fred Pierresteguy.  */
 
 #include <config.h>
-#include <signal.h>
 #include <stdio.h>
 #include <setjmp.h>
 
@@ -29,9 +28,6 @@
 
 #include "lisp.h"
 #include "blockinput.h"
-
-/* Need syssignal.h for various externs and definitions that may be required
-   by some configurations for calls to signal later in this source file.  */
 #include "syssignal.h"
 
 /* This may include sys/types.h, and that somehow loses
@@ -7766,7 +7762,9 @@
 #ifdef USG
   /* USG systems forget handlers when they are used;
      must reestablish each time */
-  signal (signalnum, x_connection_signal);
+  struct sigaction action;
+  emacs_sigaction_init (&action, x_connection_signal);
+  sigaction (signalnum, &action, 0);
 #endif /* USG */
 }
 
@@ -7788,6 +7786,7 @@
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
   ptrdiff_t idx = SPECPDL_INDEX ();
+  sigset_t unblocked;
 
   error_msg = alloca (strlen (error_message) + 1);
   strcpy (error_msg, error_message);
@@ -7876,10 +7875,12 @@
     }
 
   /* Ordinary stack unwind doesn't deal with these.  */
+  sigemptyset (&unblocked);
 #ifdef SIGIO
-  sigunblock (sigmask (SIGIO));
+  sigaddset (&unblocked, SIGIO);
 #endif
-  sigunblock (sigmask (SIGALRM));
+  sigaddset (&unblocked, SIGALRM);
+  pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
   TOTALLY_UNBLOCK_INPUT;
 
   unbind_to (idx, Qnil);
@@ -10759,6 +10760,8 @@
 void
 x_initialize (void)
 {
+  struct sigaction action;
+
   baud_rate = 19200;
 
   x_noop_count = 0;
@@ -10805,7 +10808,8 @@
   XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_io_error_quitter);
 
-  signal (SIGPIPE, x_connection_signal);
+  emacs_sigaction_init (&action, x_connection_signal);
+  sigaction (SIGPIPE, &action, 0);
 }