Diff for /gforth/engine/signals.c between versions 1.1 and 1.15

version 1.1, 1999/02/28 08:37:45 version 1.15, 2002/10/25 15:57:03
Line 1 Line 1
 /* signal handling  /* signal handling
   
   Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.    Copyright (C) 1995,1996,1997,1998,2000 Free Software Foundation, Inc.
   
   This file is part of Gforth.    This file is part of Gforth.
   
Line 16 Line 16
   
   You should have received a copy of the GNU General Public License    You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software    along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   
 */  */
   
Line 24 Line 24
 #define _GNU_SOURCE  #define _GNU_SOURCE
   
 #include <stdio.h>  #include <stdio.h>
 #include <signal.h>  
 #include <setjmp.h>  #include <setjmp.h>
 #include <string.h>  #include <string.h>
 #include <stdlib.h>  #include <stdlib.h>
 #if !defined(apollo) && !defined(MSDOS)  #if !defined(apollo) && !defined(MSDOS)
 #include <sys/ioctl.h>  #include <sys/ioctl.h>
 #endif  #endif
   /* #include <asm/signal.h> */
   #include <signal.h>
 #include "config.h"  #include "config.h"
 #include "forth.h"  #include "forth.h"
 #include "io.h"  #include "io.h"
Line 46 Line 47
 UCell cols=DEFAULTCOLS;  UCell cols=DEFAULTCOLS;
 UCell rows=DEFAULTROWS;  UCell rows=DEFAULTROWS;
   
   #ifndef SA_NODEFER
   #define SA_NODEFER 0
   /* systems that don't have SA_NODEFER hopefully don't block anyway */
   #endif
   
   #ifdef SA_SIGINFO
   void install_signal_handler(int sig, void (*handler)(int, siginfo_t *, void *))
        /* installs three-argument signal handler for sig */
   {
     struct sigaction action;
   
     action.sa_sigaction=handler;
     sigemptyset(&action.sa_mask);
     action.sa_flags=SA_RESTART|SA_NODEFER|SA_SIGINFO|SA_ONSTACK; /* pass siginfo */
     sigaction(sig, &action, NULL);
   }
   #endif
   
   typedef void Sigfunc(int);
   
   Sigfunc *bsd_signal(int signo, Sigfunc *func)
   {
     struct sigaction act, oact;
   
     act.sa_handler=func;
     sigemptyset(&act.sa_mask);
     act.sa_flags=SA_NODEFER|SA_ONSTACK;
     if (sigaction(signo,&act,&oact) < 0)
       return SIG_ERR;
     else
       return oact.sa_handler;
   }
   
 static void  static void
 graceful_exit (int sig)  graceful_exit (int sig)
Line 61  static void Line 94  static void
 signal_throw(int sig)  signal_throw(int sig)
 {  {
   int code;    int code;
   struct {  
     int signal;    switch (sig) {
     int throwcode;    case SIGINT: code=-28; break;
   } *p, throwtable[] = {    case SIGFPE: code=-55; break;
     { SIGINT, -28 },  
     { SIGFPE, -55 },  
 #ifdef SIGBUS  #ifdef SIGBUS
     { SIGBUS, -23 },    case SIGBUS: code=-23; break;
 #endif  #endif
     { SIGSEGV, -9 },    case SIGSEGV: code=-9; break;
   };    default: code=-256-sig; break;
   signal(sig,signal_throw);    }
   for (code=-256-sig, p=throwtable; p<throwtable+(sizeof(throwtable)/sizeof(*p)); p++)    longjmp(throw_jmp_buf,code); /* !! or use siglongjmp ? */
     if (sig == p->signal) {  }
       code = p->throwcode;  
       break;  #ifdef SA_SIGINFO
     }  static void fpe_handler(int sig, siginfo_t *info, void *_)
   longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */       /* handler for SIGFPE */
   {
     int code;
   
     switch(info->si_code) {
     case FPE_INTDIV: code=-10; break; /* integer divide by zero */
     case FPE_INTOVF: code=-11; break; /* integer overflow */
     case FPE_FLTDIV: code=-42; break; /* floating point divide by zero */
     case FPE_FLTOVF: code=-43; break; /* floating point overflow  */
     case FPE_FLTUND: code=-54; break; /* floating point underflow  */
     case FPE_FLTRES: code=-41; break; /* floating point inexact result  */
     case FPE_FLTINV: /* invalid floating point operation  */
     case FPE_FLTSUB: /* subscript out of range  */
     default: code=-55; break;
     }
     longjmp(throw_jmp_buf,code);
   }
   
   
   #define SPILLAGE 128
   /* if there's a SIGSEGV within SPILLAGE bytes of some stack, we assume
      that this stack has over/underflowed */
   
   #define JUSTUNDER(addr1,addr2) (((UCell)((addr2)-1-(addr1)))<SPILLAGE)
   /* true is addr1 is just under addr2 */
   
   #define JUSTOVER(addr1,addr2) (((UCell)((addr1)-(addr2)))<SPILLAGE)
   
   #define NEXTPAGE(addr) ((Address)((((UCell)(addr)-1)&-pagesize)+pagesize))
   
   static void segv_handler(int sig, siginfo_t *info, void *_)
   {
     int code=-9;
     Address addr=info->si_addr;
     ImageHeader *h=gforth_header;
   
     if (JUSTUNDER(addr, h->data_stack_base))
       code=-3;
     else if (JUSTOVER(addr, NEXTPAGE(h->data_stack_base+h->data_stack_size)))
       code=-4;
     else if (JUSTUNDER(addr, h->return_stack_base))
       code=-5;
     else if (JUSTOVER(addr, NEXTPAGE(h->return_stack_base+h->return_stack_size)))
       code=-6;
     else if (JUSTUNDER(addr, h->fp_stack_base))
       code=-44;
     else if (JUSTOVER(addr, NEXTPAGE(h->fp_stack_base+h->fp_stack_size)))
       code=-45;
     longjmp(throw_jmp_buf,code);
 }  }
   
   #endif /* defined(SA_SIGINFO) */
   
 #ifdef SIGCONT  #ifdef SIGCONT
 static void termprep (int sig)  static void termprep(int sig)
 {  {
   signal(sig,termprep);    bsd_signal(sig,termprep);
   terminal_prepped=0;    terminal_prepped=0;
 }  }
 #endif  #endif
Line 93  void get_winsize() Line 174  void get_winsize()
 {  {
 #ifdef TIOCGWINSZ  #ifdef TIOCGWINSZ
   struct winsize size;    struct winsize size;
     size.ws_row = size.ws_col = 0;
       
   if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {    if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {
     rows = size.ws_row;      rows = size.ws_row;
Line 102  void get_winsize() Line 184  void get_winsize()
   char *s;    char *s;
   if ((s=getenv("LINES"))) {    if ((s=getenv("LINES"))) {
     rows=atoi(s);      rows=atoi(s);
     if (rows==0)  
       rows=DEFAULTROWS;  
   }    }
   if ((s=getenv("COLUMNS"))) {    if ((s=getenv("COLUMNS"))) {
     rows=atoi(s);      rows=atoi(s);
     if (rows==0)  
       cols=DEFAULTCOLS;  
   }    }
 #endif  #endif
     if (rows==0)
       rows=DEFAULTROWS;
     if (rows==0)
       cols=DEFAULTCOLS;
 }  }
   
 #ifdef SIGWINCH  #ifdef SIGWINCH
 static void change_winsize(int sig)  static void change_winsize(int sig)
 {  {
   signal(sig,change_winsize);    /* signal(sig,change_winsize); should not be necessary with bsd_signal */
 #ifdef TIOCGWINSZ  #ifdef TIOCGWINSZ
   get_winsize();    get_winsize();
 #endif  #endif
 }  }
 #endif  #endif
   
 void install_signal_handlers (void)  void install_signal_handlers(void)
 {  {
   
 #if 0  #if 0
Line 256  void install_signal_handlers (void) Line 338  void install_signal_handlers (void)
 #endif  #endif
   };    };
   static short sigs_to_quit [] = {    static short sigs_to_quit [] = {
 #ifdef SIGHUP  
     SIGHUP,  
 #endif  
 #ifdef SIGQUIT  #ifdef SIGQUIT
     SIGQUIT,      SIGQUIT,
 #endif  #endif
   #ifdef SIGHUP
       SIGHUP,
   #endif
 #ifdef SIGABRT  #ifdef SIGABRT
     SIGABRT,      SIGABRT,
 #endif  #endif
Line 273  void install_signal_handlers (void) Line 355  void install_signal_handlers (void)
 #endif  #endif
   };    };
   int i;    int i;
     void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
     stack_t sigstack;
     int sas_retval=-1;
   
     sigstack.ss_size=SIGSTKSZ;
     if ((sigstack.ss_sp = my_alloc(sigstack.ss_size)) != NULL) {
       sigstack.ss_flags=0;
       sas_retval=sigaltstack(&sigstack,(stack_t *)0);
     }
     if (debug)
       fprintf(stderr,"sigaltstack: %s\n",strerror(sas_retval));
   
 #define DIM(X)          (sizeof (X) / sizeof *(X))  #define DIM(X)          (sizeof (X) / sizeof *(X))
 /*  /*
Line 280  void install_signal_handlers (void) Line 373  void install_signal_handlers (void)
     signal (sigs_to_ignore [i], SIG_IGN);      signal (sigs_to_ignore [i], SIG_IGN);
 */  */
   for (i = 0; i < DIM (sigs_to_throw); i++)    for (i = 0; i < DIM (sigs_to_throw); i++)
     signal (sigs_to_throw [i], die_on_signal ? graceful_exit : signal_throw);      bsd_signal(sigs_to_throw[i], throw_handler);
   for (i = 0; i < DIM (sigs_to_quit); i++)    for (i = 0; i < DIM (sigs_to_quit); i++)
     signal (sigs_to_quit [i], graceful_exit);      bsd_signal(sigs_to_quit [i], graceful_exit);
   #ifdef SA_SIGINFO
     if (!die_on_signal) {
       install_signal_handler(SIGFPE, fpe_handler);
       install_signal_handler(SIGSEGV, segv_handler);
     }
   #endif
 #ifdef SIGCONT  #ifdef SIGCONT
     signal (SIGCONT, termprep);      bsd_signal(SIGCONT, termprep);
 #endif  #endif
 #ifdef SIGWINCH  #ifdef SIGWINCH
     signal (SIGWINCH, change_winsize);      bsd_signal(SIGWINCH, change_winsize);
 #endif  #endif
 }  }

Removed from v.1.1  
changed lines
  Added in v.1.15


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>