diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2012-09-06 18:27:44 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2012-09-06 18:27:44 -0700 |
commit | 2fe282993cf9c84f5be424dc93d03f9705a7edd8 (patch) | |
tree | 229edb6fe29e66984b2992f3f9fa081cd7fe8920 /src/sysdep.c | |
parent | 845ce106c0ab157e25416964330875ad6c24b699 (diff) | |
download | emacs-2fe282993cf9c84f5be424dc93d03f9705a7edd8.tar.gz emacs-2fe282993cf9c84f5be424dc93d03f9705a7edd8.tar.bz2 emacs-2fe282993cf9c84f5be424dc93d03f9705a7edd8.zip |
Signal-handler cleanup.
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.
* configure.ac (PTY_OPEN, PTY_TTY_NAME_SPRINTF):
Adjust to syssignal.h changes.
(SIGNAL_H_AB): Remove; no longer needed.
* src/alloc.c, src/emacsgtkfixed.c, src/nsfns.m, src/widget.c, src/xmenu.c:
Do not include <signal.h> or "syssignal.h", as these
modules do not use signals.
* src/atimer.c, src/callproc.c, src/data.c, src/dispnew.c, src/emacs.c:
* src/floatfns.c, src/gtkutil.c, src/keyboard.c, src/process.c, src/sound.c:
* src/sysdep.c, src/term.c, src/xterm.c:
Do not include <signal.h>, as "syssignal.h" does that for us now.
* src/atimer.c (sigmask_atimers): New function.
(block_atimers, unblock_atimers): New functions,
replacing the old macros BLOCK_ATIMERS and UNBLOCK_ATIMERS.
All uses replaced.
* src/conf_post.h [SIGNAL_H_AHB]: Do not include <signal.h>;
no longer needed here.
* src/emacs.c (main): Inspect existing signal handler with sigaction,
so that there's no need to block and unblock SIGHUP.
* src/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.
* src/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.
Fixes: debbugs:12327
Diffstat (limited to 'src/sysdep.c')
-rw-r--r-- | src/sysdep.c | 111 |
1 files changed, 38 insertions, 73 deletions
diff --git a/src/sysdep.c b/src/sysdep.c index 42b8baf78e0..0f16d1a7645 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -22,7 +22,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define SYSTIME_INLINE EXTERN_INLINE #include <execinfo.h> -#include <signal.h> #include <stdio.h> #include <setjmp.h> #ifdef HAVE_PWD_H @@ -303,27 +302,34 @@ wait_for_termination_1 (pid_t pid, int interruptible) 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; } @@ -457,11 +463,11 @@ child_setup_tty (int out) #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 *); @@ -619,8 +625,9 @@ save_signal_handlers (struct save_signal *saved_handlers) { 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++; } } @@ -630,7 +637,7 @@ restore_signal_handlers (struct save_signal *saved_handlers) { while (saved_handlers->code) { - signal (saved_handlers->code, saved_handlers->handler); + sigaction (saved_handlers->code, &saved_handlers->action, 0); saved_handlers++; } } @@ -687,13 +694,17 @@ reset_sigio (int fd) 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; } @@ -701,6 +712,8 @@ request_sigio (void) void unrequest_sigio (void) { + sigset_t blocked; + if (noninteractive) return; @@ -709,10 +722,12 @@ unrequest_sigio (void) 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; } @@ -1471,20 +1486,16 @@ init_system_name (void) } } -/* 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. @@ -1501,54 +1512,8 @@ sys_signal (int signal_number, signal_handler_t action) # 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 |