File:  [gforth] / gforth / engine / signals.c
Revision 1.3: download - view: text, annotated - select for diffs
Sun Feb 28 21:31:50 1999 UTC (25 years, 1 month ago) by anton
Branches: MAIN
CVS tags: HEAD
On platforms that support the SA_SIGINFO flag (Linux is not quite
  there yet), there are now new signal handlers that perform more
  precise error reporting (in particular for SIGFPE and SIGSEGV).
Minor fixes.

    1: /* signal handling
    2: 
    3:   Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
    4: 
    5:   This file is part of Gforth.
    6: 
    7:   Gforth is free software; you can redistribute it and/or
    8:   modify it under the terms of the GNU General Public License
    9:   as published by the Free Software Foundation; either version 2
   10:   of the License, or (at your option) any later version.
   11: 
   12:   This program is distributed in the hope that it will be useful,
   13:   but WITHOUT ANY WARRANTY; without even the implied warranty of
   14:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15:   GNU General Public License for more details.
   16: 
   17:   You should have received a copy of the GNU General Public License
   18:   along with this program; if not, write to the Free Software
   19:   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   20: 
   21: */
   22: 
   23: 
   24: #define _GNU_SOURCE
   25: 
   26: #include <stdio.h>
   27: #include <setjmp.h>
   28: #include <string.h>
   29: #include <stdlib.h>
   30: #if !defined(apollo) && !defined(MSDOS)
   31: #include <sys/ioctl.h>
   32: #endif
   33: /* #include <asm/signal.h> */
   34: #include <signal.h>
   35: #include "config.h"
   36: #include "forth.h"
   37: #include "io.h"
   38: 
   39: 
   40: #define DEFAULTCOLS 80
   41: #if defined(MSDOS) || defined (_WIN32)
   42: #define DEFAULTROWS 25
   43: #else
   44: #define DEFAULTROWS 24
   45: #endif
   46: 
   47: UCell cols=DEFAULTCOLS;
   48: UCell rows=DEFAULTROWS;
   49: 
   50: 
   51: static void
   52: graceful_exit (int sig)
   53: {
   54:   deprep_terminal();
   55:   fprintf (stderr, "\n\n%s.\n", strsignal (sig));
   56:   exit (0x80|sig);
   57: }
   58: 
   59: jmp_buf throw_jmp_buf;
   60: 
   61: static void 
   62: signal_throw(int sig)
   63: {
   64:   int code;
   65: 
   66:   switch (sig) {
   67:   case SIGINT: code=-28; break;
   68:   case SIGFPE: code=-55; break;
   69: #ifdef SIGBUS
   70:   case SIGBUS: code=-23; break;
   71: #endif
   72:   case SIGSEGV: code=-9; break;
   73:   default: code=-256-sig; break;
   74:   }
   75:   longjmp(throw_jmp_buf,code); /* !! or use siglongjmp ? */
   76: }
   77: 
   78: #ifdef SA_SIGINFO
   79: static void fpe_handler(int sig, siginfo_t *info, void *_)
   80:      /* handler for SIGFPE */
   81: {
   82:   int code;
   83: 
   84:   switch(info->si_code) {
   85:   case FPE_INTDIV: code=-10; break; /* integer divide by zero */
   86:   case FPE_INTOVF: code=-11; break; /* integer overflow */
   87:   case FPE_FLTDIV: code=-42; break; /* floating point divide by zero */
   88:   case FPE_FLTOVF: code=-43; break; /* floating point overflow  */
   89:   case FPE_FLTUND: code=-54; break; /* floating point underflow  */
   90:   case FPE_FLTRES: code=-41; break; /* floating point inexact result  */
   91:   case FPE_FLTINV: /* invalid floating point operation  */
   92:   case FPE_FLTSUB: /* subscript out of range  */
   93:   default: code=-55; break;
   94:   }
   95:   longjmp(throw_jmp_buf,code);
   96: }
   97: 
   98: 
   99: #define SPILLAGE 128
  100: /* if there's a SIGSEGV within SPILLAGE bytes of some stack, we assume
  101:    that this stack has over/underflowed */
  102: 
  103: #define JUSTUNDER(addr1,addr2) (((UCell)((addr2)-1-(addr1)))<SPILLAGE)
  104: /* true is addr1 is just under addr2 */
  105: 
  106: #define JUSTOVER(addr1,addr2) (((UCell)((addr1)-(addr2)))<SPILLAGE)
  107: 
  108: #define NEXTPAGE(addr) ((Address)((((UCell)(addr)-1)&-pagesize)+pagesize))
  109: 
  110: static void segv_handler(int sig, siginfo_t *info, void *_)
  111: {
  112:   int code=-9;
  113:   Address addr=info->si_addr;
  114:   ImageHeader *h=gforth_header;
  115: 
  116:   if (JUSTUNDER(addr, h->data_stack_base))
  117:     code=-3;
  118:   else if (JUSTOVER(addr, NEXTPAGE(h->data_stack_base+h->data_stack_size)))
  119:     code=-4;
  120:   else if (JUSTUNDER(addr, h->return_stack_base))
  121:     code=-5;
  122:   else if (JUSTOVER(addr, NEXTPAGE(h->return_stack_base+h->return_stack_size)))
  123:     code=-6;
  124:   else if (JUSTUNDER(addr, h->fp_stack_base))
  125:     code=-44;
  126:   else if (JUSTOVER(addr, NEXTPAGE(h->fp_stack_base+h->fp_stack_size)))
  127:     code=-45;
  128:   longjmp(throw_jmp_buf,code);
  129: }
  130: 
  131: #endif /* defined(SA_SIGINFO) */
  132: 
  133: #ifdef SIGCONT
  134: static void termprep (int sig)
  135: {
  136:   signal(sig,termprep);
  137:   terminal_prepped=0;
  138: }
  139: #endif
  140: 
  141: void get_winsize()
  142: {
  143: #ifdef TIOCGWINSZ
  144:   struct winsize size;
  145:   
  146:   if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {
  147:     rows = size.ws_row;
  148:     cols = size.ws_col;
  149:   }
  150: #else
  151:   char *s;
  152:   if ((s=getenv("LINES"))) {
  153:     rows=atoi(s);
  154:     if (rows==0)
  155:       rows=DEFAULTROWS;
  156:   }
  157:   if ((s=getenv("COLUMNS"))) {
  158:     rows=atoi(s);
  159:     if (rows==0)
  160:       cols=DEFAULTCOLS;
  161:   }
  162: #endif
  163: }
  164: 
  165: #ifdef SIGWINCH
  166: static void change_winsize(int sig)
  167: {
  168:   signal(sig,change_winsize);
  169: #ifdef TIOCGWINSZ
  170:   get_winsize();
  171: #endif
  172: }
  173: #endif
  174: 
  175: 
  176: #ifdef SA_SIGINFO
  177: void install_signal_handler(int sig, void (*handler)(int, siginfo_t *, void *))
  178:      /* installs three-argument signal handler for sig */
  179: {
  180:   struct sigaction action;
  181: 
  182:   action.sa_sigaction=handler;
  183:   sigemptyset(&action.sa_mask);
  184:   action.sa_flags=SA_RESTART|SA_SIGINFO; /* pass siginfo */
  185:   sigaction(sig, &action, NULL);
  186: }
  187: #endif
  188: 
  189: void install_signal_handlers(void)
  190: {
  191: 
  192: #if 0
  193: /* these signals are handled right by default, no need to handle them;
  194:    they are listed here just for fun */
  195:   static short sigs_to_default [] = {
  196: #ifdef SIGCHLD
  197:     SIGCHLD,
  198: #endif
  199: #ifdef SIGINFO
  200:     SIGINFO,
  201: #endif
  202: #ifdef SIGIO
  203:     SIGIO,
  204: #endif
  205: #ifdef SIGLOST
  206:     SIGLOST,
  207: #endif
  208: #ifdef SIGKILL
  209:     SIGKILL,
  210: #endif
  211: #ifdef SIGSTOP
  212:     SIGSTOP,
  213: #endif
  214: #ifdef SIGPWR
  215:     SIGPWR,
  216: #endif
  217: #ifdef SIGMSG
  218:     SIGMSG,
  219: #endif
  220: #ifdef SIGDANGER
  221:     SIGDANGER,
  222: #endif
  223: #ifdef SIGMIGRATE
  224:     SIGMIGRATE,
  225: #endif
  226: #ifdef SIGPRE
  227:     SIGPRE,
  228: #endif
  229: #ifdef SIGVIRT
  230:     SIGVIRT,
  231: #endif
  232: #ifdef SIGGRANT
  233:     SIGGRANT,
  234: #endif
  235: #ifdef SIGRETRACT
  236:     SIGRETRACT,
  237: #endif
  238: #ifdef SIGSOUND
  239:     SIGSOUND,
  240: #endif
  241: #ifdef SIGSAK
  242:     SIGSAK,
  243: #endif
  244: #ifdef SIGTSTP
  245:     SIGTSTP,
  246: #endif
  247: #ifdef SIGTTIN
  248:     SIGTTIN,
  249: #endif
  250: #ifdef SIGTTOU
  251:     SIGTTOU,
  252: #endif
  253: #ifdef SIGSTKFLT
  254:     SIGSTKFLT,
  255: #endif
  256: #ifdef SIGUNUSED
  257:     SIGUNUSED,
  258: #endif
  259:   };
  260: #endif
  261: 
  262:   static short sigs_to_throw [] = {
  263: #ifdef SIGBREAK
  264:     SIGBREAK,
  265: #endif
  266: #ifdef SIGINT
  267:     SIGINT,
  268: #endif
  269: #ifdef SIGILL
  270:     SIGILL,
  271: #endif
  272: #ifdef SIGEMT
  273:     SIGEMT,
  274: #endif
  275: #ifdef SIGFPE
  276:     SIGFPE,
  277: #endif
  278: #ifdef SIGIOT
  279:     SIGIOT,
  280: #endif
  281: #ifdef SIGSEGV
  282:     SIGSEGV,
  283: #endif
  284: #ifdef SIGALRM
  285:     SIGALRM,
  286: #endif
  287: #ifdef SIGPIPE
  288:     SIGPIPE,
  289: #endif
  290: #ifdef SIGPOLL
  291:     SIGPOLL,
  292: #endif
  293: #ifdef SIGPROF
  294:     SIGPROF,
  295: #endif
  296: #ifdef SIGBUS
  297:     SIGBUS,
  298: #endif
  299: #ifdef SIGSYS
  300:     SIGSYS,
  301: #endif
  302: #ifdef SIGTRAP
  303:     SIGTRAP,
  304: #endif
  305: #ifdef SIGURG
  306:     SIGURG,
  307: #endif
  308: #ifdef SIGUSR1
  309:     SIGUSR1,
  310: #endif
  311: #ifdef SIGUSR2
  312:     SIGUSR2,
  313: #endif
  314: #ifdef SIGVTALRM
  315:     SIGVTALRM,
  316: #endif
  317: #ifdef SIGXFSZ
  318:     SIGXFSZ,
  319: #endif
  320:   };
  321:   static short sigs_to_quit [] = {
  322: #ifdef SIGHUP
  323:     SIGHUP,
  324: #endif
  325: #ifdef SIGQUIT
  326:     SIGQUIT,
  327: #endif
  328: #ifdef SIGABRT
  329:     SIGABRT,
  330: #endif
  331: #ifdef SIGTERM
  332:     SIGTERM,
  333: #endif
  334: #ifdef SIGXCPU
  335:     SIGXCPU,
  336: #endif
  337:   };
  338:   int i;
  339:   void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
  340: 
  341: #define DIM(X)		(sizeof (X) / sizeof *(X))
  342: /*
  343:   for (i = 0; i < DIM (sigs_to_ignore); i++)
  344:     signal (sigs_to_ignore [i], SIG_IGN);
  345: */
  346:   for (i = 0; i < DIM (sigs_to_throw); i++)
  347:     signal(sigs_to_throw[i], throw_handler);
  348:   for (i = 0; i < DIM (sigs_to_quit); i++)
  349:     signal (sigs_to_quit [i], graceful_exit);
  350: #ifdef SA_SIGINFO
  351:   install_signal_handler(SIGFPE, fpe_handler);
  352:   install_signal_handler(SIGSEGV, segv_handler);
  353: #endif
  354: #ifdef SIGCONT
  355:     signal (SIGCONT, termprep);
  356: #endif
  357: #ifdef SIGWINCH
  358:     signal (SIGWINCH, change_winsize);
  359: #endif
  360: }

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