+2012-09-06 Paul Eggert <eggert@cs.ucla.edu>
+
+ 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-04 Paul Eggert <eggert@cs.ucla.edu>
Simplify redefinition of 'abort' (Bug#12316).
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, [])
;;
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; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); if (grantpt (fd) != -1 && unlockpt (fd) != -1) ptyname = ptsname(fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 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)])
;;
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. fnf@cygnus.com
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; sigemptyset (&blocked); sigaddset (&blocked, SIGCLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 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; sigemptyset (&blocked); sigaddset (&blocked, SIGCLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); 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
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 <woods@weird.com> 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
+2012-09-06 Paul Eggert <eggert@cs.ucla.edu>
+
+ 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 (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>.
+ (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.
+
2012-09-06 Eli Zaretskii <eliz@gnu.org>
* process.c (CAN_HANDLE_MULTIPLE_CHILDREN): Fix a typo that broke
2012-09-05 Paul Eggert <eggert@cs.ucla.edu>
- Fix race conditions with signal handlers and errno.
+ Fix race conditions with signal handlers and errno (Bug#12327).
Be more systematic about preserving errno whenever a signal
handler returns, even if it's not in the main thread. Do this by
renaming signal handlers to distinguish between signal delivery
#include <limits.h> /* For CHAR_BIT. */
#include <setjmp.h>
-#include <signal.h>
-
#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif
#include "keyboard.h"
#include "frame.h"
#include "blockinput.h"
-#include "syssignal.h"
#include "termhooks.h" /* For struct terminal. */
#include <setjmp.h>
#include <verify.h>
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"
/* 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. */
t->fn = fn;
t->client_data = client_data;
- BLOCK_ATIMERS;
+ block_atimers ();
/* Compute the timer's expiration time. */
switch (type)
/* 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 ();
{
int i;
- BLOCK_ATIMERS;
+ block_atimers ();
for (i = 0; i < 2; ++i)
{
}
}
- UNBLOCK_ATIMERS;
+ unblock_atimers ();
}
void
stop_other_atimers (struct atimer *t)
{
- BLOCK_ATIMERS;
+ block_atimers ();
if (t)
{
stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
atimers = t;
- UNBLOCK_ATIMERS;
+ unblock_atimers ();
}
struct atimer *t = atimers;
struct atimer *next;
- BLOCK_ATIMERS;
+ block_atimers ();
atimers = stopped_atimers;
stopped_atimers = NULL;
t = next;
}
- UNBLOCK_ATIMERS;
+ unblock_atimers ();
}
}
{
if (pending_atimers)
{
- BLOCK_ATIMERS;
+ block_atimers ();
run_timers ();
- UNBLOCK_ATIMERS;
+ unblock_atimers ();
}
}
{
if (on)
{
- signal (SIGALRM, deliver_alarm_signal);
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_alarm_signal);
+ sigaction (SIGALRM, &action, 0);
set_alarm ();
}
else
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, deliver_alarm_signal);
+ emacs_sigaction_init (&action, deliver_alarm_signal);
+ sigaction (SIGALRM, &action, 0);
}
#include <config.h>
-#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <setjmp.h>
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;
#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
#include <config.h>
-#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
static _Noreturn void
handle_arith_signal (int sig)
{
- sigsetmask (SIGEMPTYMASK);
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
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
if (!initialized)
return;
#endif /* CANNOT_DUMP */
- signal (SIGFPE, deliver_arith_signal);
+ emacs_sigaction_init (&action, deliver_arith_signal);
+ sigaction (SIGFPE, &action, 0);
}
#define DISPEXTERN_INLINE EXTERN_INLINE
-#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
#include <unistd.h>
int width, height;
struct tty_display_info *tty;
- signal (SIGWINCH, deliver_window_change_signal);
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_window_change_signal);
+ sigaction (SIGWINCH, &action, 0);
/* The frame size change obviously applies to a single
termcap-controlled terminal, but we can't decide which.
#ifndef CANNOT_DUMP
if (initialized)
#endif /* CANNOT_DUMP */
- signal (SIGWINCH, deliver_window_change_signal);
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_window_change_signal);
+ sigaction (SIGWINCH, &action, 0);
+ }
#endif /* SIGWINCH */
/* If running as a daemon, no need to initialize any frames/terminal. */
#include <config.h>
-#include <signal.h>
#include <errno.h>
#include <stdio.h>
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));
+ {
+ sigset_t unblocked;
+ sigemptyset (&unblocked);
+ sigaddset (&unblocked, fatal_error_code);
+ pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
+ }
#endif
kill (getpid (), fatal_error_code);
static void
handle_danger_signal (int sig)
{
- signal (sig, deliver_danger_signal);
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_danger_signal);
+ sigaction (sig, &action, 0);
+
malloc_warning ("Operating system warns that virtual memory is running low.\n");
/* It might be unsafe to call do_auto_save now. */
char dname_arg2[80];
#endif
char *ch_to_dir;
+ struct sigaction fatal_error_action;
#if GC_MARK_STACK
stack_base = &dummy;
}
init_signals ();
+ emacs_sigaction_init (&fatal_error_action, deliver_fatal_signal);
/* Don't catch SIGHUP if dumping. */
if (1
#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, deliver_fatal_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 (
add_user_signal (SIGUSR2, "sigusr2");
#endif
#ifdef SIGABRT
- signal (SIGABRT, deliver_fatal_signal);
+ sigaction (SIGABRT, &fatal_error_action, 0);
#endif
#ifdef SIGHWE
- signal (SIGHWE, deliver_fatal_signal);
+ sigaction (SIGHWE, &fatal_error_action, 0);
#endif
#ifdef SIGPRE
- signal (SIGPRE, deliver_fatal_signal);
+ sigaction (SIGPRE, &fatal_error_action, 0);
#endif
#ifdef SIGORE
- signal (SIGORE, deliver_fatal_signal);
+ sigaction (SIGORE, &fatal_error_action, 0);
#endif
#ifdef SIGUME
- signal (SIGUME, deliver_fatal_signal);
+ sigaction (SIGUME, &fatal_error_action, 0);
#endif
#ifdef SIGDLK
- signal (SIGDLK, deliver_fatal_signal);
+ sigaction (SIGDLK, &fatal_error_action, 0);
#endif
#ifdef SIGCPULIM
- signal (SIGCPULIM, deliver_fatal_signal);
+ sigaction (SIGCPULIM, &fatal_error_action, 0);
#endif
#ifdef SIGIOT
/* This is missing on some systems - OS/2, for example. */
- signal (SIGIOT, deliver_fatal_signal);
+ sigaction (SIGIOT, &fatal_error_action, 0);
#endif
#ifdef SIGEMT
- signal (SIGEMT, deliver_fatal_signal);
+ sigaction (SIGEMT, &fatal_error_action, 0);
#endif
- signal (SIGFPE, deliver_fatal_signal);
+ sigaction (SIGFPE, &fatal_error_action, 0);
#ifdef SIGBUS
- signal (SIGBUS, deliver_fatal_signal);
+ sigaction (SIGBUS, &fatal_error_action, 0);
#endif
- signal (SIGSEGV, deliver_fatal_signal);
+ sigaction (SIGSEGV, &fatal_error_action, 0);
#ifdef SIGSYS
- signal (SIGSYS, deliver_fatal_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, deliver_fatal_signal);
- signal (SIGTERM, deliver_fatal_signal);
+ if (noninteractive)
+ sigaction (SIGINT, &fatal_error_action, 0);
+ sigaction (SIGTERM, &fatal_error_action, 0);
#ifdef SIGXCPU
- signal (SIGXCPU, deliver_fatal_signal);
+ sigaction (SIGXCPU, &fatal_error_action, 0);
#endif
#ifdef SIGXFSZ
- signal (SIGXFSZ, deliver_fatal_signal);
+ sigaction (SIGXFSZ, &fatal_error_action, 0);
#endif /* SIGXFSZ */
#ifdef SIGDANGER
/* This just means available memory is getting low. */
- signal (SIGDANGER, deliver_danger_signal);
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_danger_signal);
+ sigaction (SIGDANGER, &action, 0);
+ }
#endif
#ifdef AIX
/* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU. */
- signal (SIGXCPU, deliver_fatal_signal);
- signal (SIGIOINT, deliver_fatal_signal);
- signal (SIGGRANT, deliver_fatal_signal);
- signal (SIGRETRACT, deliver_fatal_signal);
- signal (SIGSOUND, deliver_fatal_signal);
- signal (SIGMSG, deliver_fatal_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 */
}
#include <config.h>
#include "emacsgtkfixed.h"
-#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
#include "lisp.h"
*/
#include <config.h>
-#include <signal.h>
#include <setjmp.h>
#include "lisp.h"
#include "syssignal.h"
#ifdef USE_GTK
#include <float.h>
-#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
/* 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
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)
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
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)
#define KEYBOARD_INLINE EXTERN_INLINE
-#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
#include "lisp.h"
if (immediate_quit && NILP (Vinhibit_quit))
{
immediate_quit = 0;
- sigfree ();
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
QUIT;
}
}
unhold_keyboard_input ();
#ifdef SIGIO
if (!noninteractive)
- signal (SIGIO, deliver_input_available_signal);
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_input_available_signal);
+ sigaction (SIGIO, &action, 0);
+ }
#endif /* SIGIO */
start_polling ();
}
#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
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
#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
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)
p->next = user_signals;
user_signals = p;
- signal (sig, deliver_user_signal);
+ emacs_sigaction_init (&action, deliver_user_signal);
+ sigaction (sig, &action, 0);
}
static void
for (p = user_signals; p; p = p->next)
if (p->npending > 0)
{
- SIGMASKTYPE mask;
+ sigset_t blocked, procmask;
if (nstored == 0)
{
}
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;
p->npending--;
}
while (p->npending > 0);
- sigsetmask (mask);
+
+ pthread_sigmask (SIG_SETMASK, &procmask, 0);
}
return nstored;
/* 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 ();
#endif /* not MSDOS */
fflush (stdout);
init_all_sys_modes ();
- sigfree ();
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
}
else
{
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);
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;
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, deliver_interrupt_signal);
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_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, deliver_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, deliver_input_available_signal);
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_input_available_signal);
+ sigaction (SIGIO, &action, 0);
+ }
#endif /* SIGIO */
/* Use interrupt input by default, if it works and noninterrupt input
interrupt_input = 0;
#endif
- sigfree ();
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
dribble = 0;
if (keyboard_init_hook)
interpretation of even the system includes. */
#include <config.h>
-#include <signal.h>
#include <math.h>
#include <setjmp.h>
#include <c-strcase.h>
#define PROCESS_INLINE EXTERN_INLINE
-#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <setjmp.h>
#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;
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. */
static _Noreturn void
handle_pipe_signal (int sig)
{
- sigunblock (sigmask (SIGPIPE));
+ sigset_t unblocked;
+ sigemptyset (&unblocked);
+ sigaddset (&unblocked, SIGPIPE);
+ pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
_longjmp (send_process_frame, 1);
}
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);
/* Send this batch, using one or more write calls. */
ptrdiff_t written = 0;
int outfd = p->outfd;
- old_sigpipe = signal (SIGPIPE, deliver_pipe_signal);
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_pipe_signal);
+ sigaction (SIGPIPE, &action, &old_sigpipe_action);
#ifdef DATAGRAM_SOCKETS
if (DATAGRAM_CHAN_P (outfd))
{
written = rv;
else if (errno == EMSGSIZE)
{
- signal (SIGPIPE, old_sigpipe);
+ sigaction (SIGPIPE, &old_sigpipe_action, 0);
report_file_error ("sending datagram",
Fcons (proc, Qnil));
}
}
#endif
}
- signal (SIGPIPE, old_sigpipe);
+ sigaction (SIGPIPE, &old_sigpipe_action, 0);
if (rv < 0)
{
}
else
{
- signal (SIGPIPE, old_sigpipe);
+ sigaction (SIGPIPE, &old_sigpipe_action, 0);
proc = process_sent_to;
p = XPROCESS (proc);
p->raw_status_new = 0;
#ifndef CANNOT_DUMP
if (! noninteractive || initialized)
#endif
- signal (SIGCHLD, deliver_child_signal);
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_child_signal);
+ sigaction (SIGCHLD, &action, 0);
+ }
#endif
FD_ZERO (&input_wait_mask);
#include "lisp.h"
#include "dispextern.h"
#include "atimer.h"
-#include <signal.h>
#include "syssignal.h"
/* END: Common Includes */
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));
vox_configure (struct sound_device *sd)
{
int val;
+#ifdef SIGIO
+ sigset_t blocked;
+#endif
eassert (sd->fd >= 0);
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;
turn_on_atimers (1);
#ifdef SIGIO
- sigunblock (sigmask (SIGIO));
+ pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
#endif
}
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);
turn_on_atimers (1);
#ifdef SIGIO
- sigunblock (sigmask (SIGIO));
+ pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
#endif
/* Close the device. */
#define SYSTIME_INLINE EXTERN_INLINE
#include <execinfo.h>
-#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
#ifdef HAVE_PWD_H
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;
}
#endif /* not MSDOS */
\f
-/* 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 *);
{
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++;
}
}
{
while (saved_handlers->code)
{
- signal (saved_handlers->code, saved_handlers->handler);
+ sigaction (saved_handlers->code, &saved_handlers->action, 0);
saved_handlers++;
}
}
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;
}
void
unrequest_sigio (void)
{
+ sigset_t blocked;
+
if (noninteractive)
return;
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;
}
}
}
\f
-/* 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.
# if defined (BROKEN_SA_RESTART) || defined (SYNC_INPUT)
if (noninteractive)
# endif
- new_action.sa_flags = SA_RESTART;
+ 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);
}
#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
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>
+
extern void init_signals (void);
#ifdef HAVE_PTHREAD
#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)
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
#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
#include <sys/file.h>
#include <sys/time.h>
#include <unistd.h>
-#include <signal.h>
#include <setjmp.h>
#include "lisp.h"
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)
{
}
if (fd != -1)
emacs_close (fd);
- sigunblock (sigmask (SIGTTOU));
+ pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
#else
/* Unknown system. */
croak ();
/* On some systems, tgetent tries to access the controlling
terminal. */
- sigblock (sigmask (SIGTTOU));
- status = tgetent (tty->termcap_term_buffer, terminal_type);
- sigunblock (sigmask (SIGTTOU));
+ {
+ sigset_t blocked;
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGTTOU);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
+ status = tgetent (tty->termcap_term_buffer, terminal_type);
+ pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
+ }
if (status < 0)
{
#include <X11/ShellP.h>
#include "../lwlib/lwlib.h"
-#include <signal.h>
-#include "syssignal.h"
-
#include "character.h"
#include "font.h"
#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>
/* Xt features made by Fred Pierresteguy. */
#include <config.h>
-#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
#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
#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 */
}
}
/* Ordinary stack unwind doesn't deal with these. */
+ {
+ sigset_t unblocked;
+ 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);
void
x_initialize (void)
{
+ struct sigaction action;
+
baud_rate = 19200;
x_noop_count = 0;
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);
}