aboutsummaryrefslogtreecommitdiffstats
path: root/src/sysdep.c
diff options
context:
space:
mode:
authorPaul Eggert2012-09-06 18:27:44 -0700
committerPaul Eggert2012-09-06 18:27:44 -0700
commit2fe282993cf9c84f5be424dc93d03f9705a7edd8 (patch)
tree229edb6fe29e66984b2992f3f9fa081cd7fe8920 /src/sysdep.c
parent845ce106c0ab157e25416964330875ad6c24b699 (diff)
downloademacs-2fe282993cf9c84f5be424dc93d03f9705a7edd8.tar.gz
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.c111
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/>. */
22#define SYSTIME_INLINE EXTERN_INLINE 22#define SYSTIME_INLINE EXTERN_INLINE
23 23
24#include <execinfo.h> 24#include <execinfo.h>
25#include <signal.h>
26#include <stdio.h> 25#include <stdio.h>
27#include <setjmp.h> 26#include <setjmp.h>
28#ifdef HAVE_PWD_H 27#ifdef HAVE_PWD_H
@@ -303,27 +302,34 @@ wait_for_termination_1 (pid_t pid, int interruptible)
303 termination of subprocesses, perhaps involving a kernel bug too, 302 termination of subprocesses, perhaps involving a kernel bug too,
304 but no idea what it is. Just as a hunch we signal SIGCHLD to see 303 but no idea what it is. Just as a hunch we signal SIGCHLD to see
305 if that causes the problem to go away or get worse. */ 304 if that causes the problem to go away or get worse. */
306 sigsetmask (sigmask (SIGCHLD)); 305 sigset_t sigchild_mask;
306 sigemptyset (&sigchild_mask);
307 sigaddset (&sigchild_mask, SIGCHLD);
308 pthread_sigmask (SIG_SETMASK, &sigchild_mask, 0);
309
307 if (0 > kill (pid, 0)) 310 if (0 > kill (pid, 0))
308 { 311 {
309 sigsetmask (SIGEMPTYMASK); 312 pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
310 kill (getpid (), SIGCHLD); 313 kill (getpid (), SIGCHLD);
311 break; 314 break;
312 } 315 }
313 if (wait_debugging) 316 if (wait_debugging)
314 sleep (1); 317 sleep (1);
315 else 318 else
316 sigpause (SIGEMPTYMASK); 319 sigsuspend (&empty_mask);
317#else /* not BSD_SYSTEM, and not HPUX version >= 6 */ 320#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
318#ifdef WINDOWSNT 321#ifdef WINDOWSNT
319 wait (0); 322 wait (0);
320 break; 323 break;
321#else /* not WINDOWSNT */ 324#else /* not WINDOWSNT */
322 sigblock (sigmask (SIGCHLD)); 325 sigset_t blocked;
326 sigemptyset (&blocked);
327 sigaddset (&blocked, SIGCHLD);
328 pthread_sigmask (SIG_BLOCK, &blocked, 0);
323 errno = 0; 329 errno = 0;
324 if (kill (pid, 0) == -1 && errno == ESRCH) 330 if (kill (pid, 0) == -1 && errno == ESRCH)
325 { 331 {
326 sigunblock (sigmask (SIGCHLD)); 332 pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
327 break; 333 break;
328 } 334 }
329 335
@@ -457,11 +463,11 @@ child_setup_tty (int out)
457#endif /* not MSDOS */ 463#endif /* not MSDOS */
458 464
459 465
460/* Record a signal code and the handler for it. */ 466/* Record a signal code and the action for it. */
461struct save_signal 467struct save_signal
462{ 468{
463 int code; 469 int code;
464 void (*handler) (int); 470 struct sigaction action;
465}; 471};
466 472
467static void save_signal_handlers (struct save_signal *); 473static void save_signal_handlers (struct save_signal *);
@@ -619,8 +625,9 @@ save_signal_handlers (struct save_signal *saved_handlers)
619{ 625{
620 while (saved_handlers->code) 626 while (saved_handlers->code)
621 { 627 {
622 saved_handlers->handler 628 struct sigaction action;
623 = (void (*) (int)) signal (saved_handlers->code, SIG_IGN); 629 emacs_sigaction_init (&action, SIG_IGN);
630 sigaction (saved_handlers->code, &action, &saved_handlers->action);
624 saved_handlers++; 631 saved_handlers++;
625 } 632 }
626} 633}
@@ -630,7 +637,7 @@ restore_signal_handlers (struct save_signal *saved_handlers)
630{ 637{
631 while (saved_handlers->code) 638 while (saved_handlers->code)
632 { 639 {
633 signal (saved_handlers->code, saved_handlers->handler); 640 sigaction (saved_handlers->code, &saved_handlers->action, 0);
634 saved_handlers++; 641 saved_handlers++;
635 } 642 }
636} 643}
@@ -687,13 +694,17 @@ reset_sigio (int fd)
687void 694void
688request_sigio (void) 695request_sigio (void)
689{ 696{
697 sigset_t unblocked;
698
690 if (noninteractive) 699 if (noninteractive)
691 return; 700 return;
692 701
702 sigemptyset (&unblocked);
693#ifdef SIGWINCH 703#ifdef SIGWINCH
694 sigunblock (sigmask (SIGWINCH)); 704 sigaddset (&unblocked, SIGWINCH);
695#endif 705#endif
696 sigunblock (sigmask (SIGIO)); 706 sigaddset (&unblocked, SIGIO);
707 pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
697 708
698 interrupts_deferred = 0; 709 interrupts_deferred = 0;
699} 710}
@@ -701,6 +712,8 @@ request_sigio (void)
701void 712void
702unrequest_sigio (void) 713unrequest_sigio (void)
703{ 714{
715 sigset_t blocked;
716
704 if (noninteractive) 717 if (noninteractive)
705 return; 718 return;
706 719
@@ -709,10 +722,12 @@ unrequest_sigio (void)
709 return; 722 return;
710#endif 723#endif
711 724
725 sigemptyset (&blocked);
712#ifdef SIGWINCH 726#ifdef SIGWINCH
713 sigblock (sigmask (SIGWINCH)); 727 sigaddset (&blocked, SIGWINCH);
714#endif 728#endif
715 sigblock (sigmask (SIGIO)); 729 sigaddset (&blocked, SIGIO);
730 pthread_sigmask (SIG_BLOCK, &blocked, 0);
716 interrupts_deferred = 1; 731 interrupts_deferred = 1;
717} 732}
718 733
@@ -1471,20 +1486,16 @@ init_system_name (void)
1471 } 1486 }
1472} 1487}
1473 1488
1474/* POSIX signals support - DJB */
1475/* Anyone with POSIX signals should have ANSI C declarations */
1476
1477sigset_t empty_mask; 1489sigset_t empty_mask;
1478 1490
1479#ifndef WINDOWSNT 1491/* Store into *ACTION a signal action suitable for Emacs, with handler
1480 1492 HANDLER. */
1481signal_handler_t 1493void
1482sys_signal (int signal_number, signal_handler_t action) 1494emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
1483{ 1495{
1484 struct sigaction new_action, old_action; 1496 sigemptyset (&action->sa_mask);
1485 sigemptyset (&new_action.sa_mask); 1497 action->sa_handler = handler;
1486 new_action.sa_handler = action; 1498 action->sa_flags = 0;
1487 new_action.sa_flags = 0;
1488#if defined (SA_RESTART) 1499#if defined (SA_RESTART)
1489 /* Emacs mostly works better with restartable system services. If this 1500 /* Emacs mostly works better with restartable system services. If this
1490 flag exists, we probably want to turn it on here. 1501 flag exists, we probably want to turn it on here.
@@ -1501,54 +1512,8 @@ sys_signal (int signal_number, signal_handler_t action)
1501# if defined (BROKEN_SA_RESTART) || defined (SYNC_INPUT) 1512# if defined (BROKEN_SA_RESTART) || defined (SYNC_INPUT)
1502 if (noninteractive) 1513 if (noninteractive)
1503# endif 1514# endif
1504 new_action.sa_flags = SA_RESTART; 1515 action->sa_flags = SA_RESTART;
1505#endif 1516#endif
1506 sigaction (signal_number, &new_action, &old_action);
1507 return (old_action.sa_handler);
1508}
1509
1510#endif /* WINDOWSNT */
1511
1512#ifndef __GNUC__
1513/* If we're compiling with GCC, we don't need this function, since it
1514 can be written as a macro. */
1515sigset_t
1516sys_sigmask (int sig)
1517{
1518 sigset_t mask;
1519 sigemptyset (&mask);
1520 sigaddset (&mask, sig);
1521 return mask;
1522}
1523#endif
1524
1525/* I'd like to have these guys return pointers to the mask storage in here,
1526 but there'd be trouble if the code was saving multiple masks. I'll be
1527 safe and pass the structure. It normally won't be more than 2 bytes
1528 anyhow. - DJB */
1529
1530sigset_t
1531sys_sigblock (sigset_t new_mask)
1532{
1533 sigset_t old_mask;
1534 pthread_sigmask (SIG_BLOCK, &new_mask, &old_mask);
1535 return (old_mask);
1536}
1537
1538sigset_t
1539sys_sigunblock (sigset_t new_mask)
1540{
1541 sigset_t old_mask;
1542 pthread_sigmask (SIG_UNBLOCK, &new_mask, &old_mask);
1543 return (old_mask);
1544}
1545
1546sigset_t
1547sys_sigsetmask (sigset_t new_mask)
1548{
1549 sigset_t old_mask;
1550 pthread_sigmask (SIG_SETMASK, &new_mask, &old_mask);
1551 return (old_mask);
1552} 1517}
1553 1518
1554#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD 1519#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD