File:  [gforth] / gforth / engine / signals.c
Revision 1.19: download - view: text, annotated - select for diffs
Tue Dec 24 23:40:30 2002 UTC (21 years, 3 months ago) by anton
Branches: MAIN
CVS tags: HEAD
Gforth now supports large files (>2GB) on small machines (32-bits/cell).
forth.h now asks for all kinds of POSIX, X/Open, and GNU support.
rearranged include files such that forth.h precedes the system files.

    1: /* signal handling
    2: 
    3:   Copyright (C) 1995,1996,1997,1998,2000 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., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   20: 
   21: */
   22: 
   23: 
   24: #include "config.h"
   25: #include "forth.h"
   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 "io.h"
   36: 
   37: 
   38: #define DEFAULTCOLS 80
   39: #if defined(MSDOS) || defined (_WIN32)
   40: #define DEFAULTROWS 25
   41: #else
   42: #define DEFAULTROWS 24
   43: #endif
   44: 
   45: UCell cols=DEFAULTCOLS;
   46: UCell rows=DEFAULTROWS;
   47: 
   48: #ifndef SA_NODEFER
   49: #define SA_NODEFER 0
   50: /* systems that don't have SA_NODEFER hopefully don't block anyway */
   51: #endif
   52: 
   53: #ifndef SA_ONSTACK
   54: #define SA_ONSTACK 0
   55: #endif
   56: 
   57: #ifdef SA_SIGINFO
   58: void install_signal_handler(int sig, void (*handler)(int, siginfo_t *, void *))
   59:      /* installs three-argument signal handler for sig */
   60: {
   61:   struct sigaction action;
   62: 
   63:   action.sa_sigaction=handler;
   64:   sigemptyset(&action.sa_mask);
   65:   action.sa_flags=SA_RESTART|SA_NODEFER|SA_SIGINFO|SA_ONSTACK; /* pass siginfo */
   66:   sigaction(sig, &action, NULL);
   67: }
   68: #endif
   69: 
   70: typedef void Sigfunc(int);
   71: 
   72: Sigfunc *bsd_signal(int signo, Sigfunc *func)
   73: {
   74:   struct sigaction act, oact;
   75: 
   76:   act.sa_handler=func;
   77:   sigemptyset(&act.sa_mask);
   78:   act.sa_flags=SA_NODEFER; /* SA_ONSTACK does not work for graceful_exit */
   79:   if (sigaction(signo,&act,&oact) < 0)
   80:     return SIG_ERR;
   81:   else
   82:     return oact.sa_handler;
   83: }
   84: 
   85: static void
   86: graceful_exit (int sig)
   87: {
   88:   deprep_terminal();
   89:   fprintf (stderr, "\n\n%s.\n", strsignal (sig));
   90:   exit (0x80|sig);
   91: }
   92: 
   93: jmp_buf throw_jmp_buf;
   94: 
   95: static void 
   96: signal_throw(int sig)
   97: {
   98:   int code;
   99: 
  100:   switch (sig) {
  101:   case SIGINT: code=-28; break;
  102:   case SIGFPE: code=-55; break;
  103: #ifdef SIGBUS
  104:   case SIGBUS: code=-23; break;
  105: #endif
  106:   case SIGSEGV: code=-9; break;
  107:   default: code=-256-sig; break;
  108:   }
  109:   longjmp(throw_jmp_buf,code); /* !! or use siglongjmp ? */
  110: }
  111: 
  112: #ifdef SA_SIGINFO
  113: static void fpe_handler(int sig, siginfo_t *info, void *_)
  114:      /* handler for SIGFPE */
  115: {
  116:   int code;
  117: 
  118:   switch(info->si_code) {
  119: #ifdef FPE_INTDIV
  120:   case FPE_INTDIV: code=-10; break; /* integer divide by zero */
  121: #endif
  122: #ifdef FPE_INTOVF
  123:   case FPE_INTOVF: code=-11; break; /* integer overflow */
  124: #endif
  125:   case FPE_FLTDIV: code=-42; break; /* floating point divide by zero */
  126:   case FPE_FLTOVF: code=-43; break; /* floating point overflow  */
  127:   case FPE_FLTUND: code=-54; break; /* floating point underflow  */
  128:   case FPE_FLTRES: code=-41; break; /* floating point inexact result  */
  129: #if 0 /* defined by Unix95, but unnecessary */
  130:   case FPE_FLTINV: /* invalid floating point operation  */
  131:   case FPE_FLTSUB: /* subscript out of range  */
  132: #endif
  133:   default: code=-55; break;
  134:   }
  135:   longjmp(throw_jmp_buf,code);
  136: }
  137: 
  138: 
  139: #define SPILLAGE 128
  140: /* if there's a SIGSEGV within SPILLAGE bytes of some stack, we assume
  141:    that this stack has over/underflowed */
  142: 
  143: #define JUSTUNDER(addr1,addr2) (((UCell)((addr2)-1-(addr1)))<SPILLAGE)
  144: /* true is addr1 is just under addr2 */
  145: 
  146: #define JUSTOVER(addr1,addr2) (((UCell)((addr1)-(addr2)))<SPILLAGE)
  147: 
  148: #define NEXTPAGE(addr) ((Address)((((UCell)(addr)-1)&-pagesize)+pagesize))
  149: 
  150: static void segv_handler(int sig, siginfo_t *info, void *_)
  151: {
  152:   int code=-9;
  153:   Address addr=info->si_addr;
  154:   ImageHeader *h=gforth_header;
  155: 
  156:   if (JUSTUNDER(addr, h->data_stack_base))
  157:     code=-3;
  158:   else if (JUSTOVER(addr, NEXTPAGE(h->data_stack_base+h->data_stack_size)))
  159:     code=-4;
  160:   else if (JUSTUNDER(addr, h->return_stack_base))
  161:     code=-5;
  162:   else if (JUSTOVER(addr, NEXTPAGE(h->return_stack_base+h->return_stack_size)))
  163:     code=-6;
  164:   else if (JUSTUNDER(addr, h->fp_stack_base))
  165:     code=-44;
  166:   else if (JUSTOVER(addr, NEXTPAGE(h->fp_stack_base+h->fp_stack_size)))
  167:     code=-45;
  168:   longjmp(throw_jmp_buf,code);
  169: }
  170: 
  171: #endif /* defined(SA_SIGINFO) */
  172: 
  173: #ifdef SIGCONT
  174: static void termprep(int sig)
  175: {
  176:   bsd_signal(sig,termprep);
  177:   terminal_prepped=0;
  178: }
  179: #endif
  180: 
  181: void get_winsize()
  182: {
  183: #ifdef TIOCGWINSZ
  184:   struct winsize size;
  185:   size.ws_row = size.ws_col = 0;
  186:   
  187:   if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {
  188:     rows = size.ws_row;
  189:     cols = size.ws_col;
  190:   }
  191: #else
  192:   char *s;
  193:   if ((s=getenv("LINES"))) {
  194:     rows=atoi(s);
  195:   }
  196:   if ((s=getenv("COLUMNS"))) {
  197:     rows=atoi(s);
  198:   }
  199: #endif
  200:   if (rows==0)
  201:     rows=DEFAULTROWS;
  202:   if (rows==0)
  203:     cols=DEFAULTCOLS;
  204: }
  205: 
  206: #ifdef SIGWINCH
  207: static void change_winsize(int sig)
  208: {
  209:   /* signal(sig,change_winsize); should not be necessary with bsd_signal */
  210: #ifdef TIOCGWINSZ
  211:   get_winsize();
  212: #endif
  213: }
  214: #endif
  215: 
  216: void install_signal_handlers(void)
  217: {
  218: 
  219: #if 0
  220: /* these signals are handled right by default, no need to handle them;
  221:    they are listed here just for fun */
  222:   static short sigs_to_default [] = {
  223: #ifdef SIGCHLD
  224:     SIGCHLD,
  225: #endif
  226: #ifdef SIGINFO
  227:     SIGINFO,
  228: #endif
  229: #ifdef SIGIO
  230:     SIGIO,
  231: #endif
  232: #ifdef SIGLOST
  233:     SIGLOST,
  234: #endif
  235: #ifdef SIGKILL
  236:     SIGKILL,
  237: #endif
  238: #ifdef SIGSTOP
  239:     SIGSTOP,
  240: #endif
  241: #ifdef SIGPWR
  242:     SIGPWR,
  243: #endif
  244: #ifdef SIGMSG
  245:     SIGMSG,
  246: #endif
  247: #ifdef SIGDANGER
  248:     SIGDANGER,
  249: #endif
  250: #ifdef SIGMIGRATE
  251:     SIGMIGRATE,
  252: #endif
  253: #ifdef SIGPRE
  254:     SIGPRE,
  255: #endif
  256: #ifdef SIGVIRT
  257:     SIGVIRT,
  258: #endif
  259: #ifdef SIGGRANT
  260:     SIGGRANT,
  261: #endif
  262: #ifdef SIGRETRACT
  263:     SIGRETRACT,
  264: #endif
  265: #ifdef SIGSOUND
  266:     SIGSOUND,
  267: #endif
  268: #ifdef SIGSAK
  269:     SIGSAK,
  270: #endif
  271: #ifdef SIGTSTP
  272:     SIGTSTP,
  273: #endif
  274: #ifdef SIGTTIN
  275:     SIGTTIN,
  276: #endif
  277: #ifdef SIGTTOU
  278:     SIGTTOU,
  279: #endif
  280: #ifdef SIGSTKFLT
  281:     SIGSTKFLT,
  282: #endif
  283: #ifdef SIGUNUSED
  284:     SIGUNUSED,
  285: #endif
  286:   };
  287: #endif
  288: 
  289:   static short sigs_to_throw [] = {
  290: #ifdef SIGBREAK
  291:     SIGBREAK,
  292: #endif
  293: #ifdef SIGINT
  294:     SIGINT,
  295: #endif
  296: #ifdef SIGILL
  297:     SIGILL,
  298: #endif
  299: #ifdef SIGEMT
  300:     SIGEMT,
  301: #endif
  302: #ifdef SIGFPE
  303:     SIGFPE,
  304: #endif
  305: #ifdef SIGIOT
  306:     SIGIOT,
  307: #endif
  308: #ifdef SIGSEGV
  309:     SIGSEGV,
  310: #endif
  311: #ifdef SIGALRM
  312:     SIGALRM,
  313: #endif
  314: #ifdef SIGPIPE
  315:     SIGPIPE,
  316: #endif
  317: #ifdef SIGPOLL
  318:     SIGPOLL,
  319: #endif
  320: #ifdef SIGPROF
  321:     SIGPROF,
  322: #endif
  323: #ifdef SIGBUS
  324:     SIGBUS,
  325: #endif
  326: #ifdef SIGSYS
  327:     SIGSYS,
  328: #endif
  329: #ifdef SIGTRAP
  330:     SIGTRAP,
  331: #endif
  332: #ifdef SIGURG
  333:     SIGURG,
  334: #endif
  335: #ifdef SIGUSR1
  336:     SIGUSR1,
  337: #endif
  338: #ifdef SIGUSR2
  339:     SIGUSR2,
  340: #endif
  341: #ifdef SIGVTALRM
  342:     SIGVTALRM,
  343: #endif
  344: #ifdef SIGXFSZ
  345:     SIGXFSZ,
  346: #endif
  347:   };
  348:   static short sigs_to_quit [] = {
  349: #ifdef SIGQUIT
  350:     SIGQUIT,
  351: #endif
  352: #ifdef SIGHUP
  353:     SIGHUP,
  354: #endif
  355: #ifdef SIGABRT
  356:     SIGABRT,
  357: #endif
  358: #ifdef SIGTERM
  359:     SIGTERM,
  360: #endif
  361: #ifdef SIGXCPU
  362:     SIGXCPU,
  363: #endif
  364:   };
  365:   int i;
  366:   void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
  367: #ifdef SIGSTKSZ 
  368:   stack_t sigstack;
  369:   int sas_retval=-1;
  370: 
  371:   sigstack.ss_size=SIGSTKSZ;
  372:   if ((sigstack.ss_sp = my_alloc(sigstack.ss_size)) != NULL) {
  373:     sigstack.ss_flags=0;
  374:     sas_retval=sigaltstack(&sigstack,(stack_t *)0);
  375:   }
  376:   if (debug)
  377:     fprintf(stderr,"sigaltstack: %s\n",strerror(sas_retval));
  378: #endif
  379: 
  380: #define DIM(X)		(sizeof (X) / sizeof *(X))
  381: /*
  382:   for (i = 0; i < DIM (sigs_to_ignore); i++)
  383:     signal (sigs_to_ignore [i], SIG_IGN);
  384: */
  385:   for (i = 0; i < DIM (sigs_to_throw); i++)
  386:     bsd_signal(sigs_to_throw[i], throw_handler);
  387:   for (i = 0; i < DIM (sigs_to_quit); i++)
  388:     bsd_signal(sigs_to_quit [i], graceful_exit);
  389: #ifdef SA_SIGINFO
  390:   if (!die_on_signal) {
  391:     install_signal_handler(SIGFPE, fpe_handler);
  392:     install_signal_handler(SIGSEGV, segv_handler);
  393:   }
  394: #endif
  395: #ifdef SIGCONT
  396:     bsd_signal(SIGCONT, termprep);
  397: #endif
  398: #ifdef SIGWINCH
  399:     bsd_signal(SIGWINCH, change_winsize);
  400: #endif
  401: }

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