File:  [gforth] / gforth / engine / signals.c
Revision 1.18: download - view: text, annotated - select for diffs
Sat Nov 2 15:26:03 2002 UTC (19 years, 9 months ago) by anton
Branches: MAIN
CVS tags: HEAD
New file test/float.fs
FROUND-OFFSET now defined without f**
bugfix in signals (disabled SA_ONSTACK in most cases to allow graceful_exit).

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

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