File:  [gforth] / gforth / engine / signals.c
Revision 1.11: download - view: text, annotated - select for diffs
Sat Sep 23 15:47:08 2000 UTC (23 years, 6 months ago) by anton
Branches: MAIN
CVS tags: v0-5-0, HEAD
changed FSF address in copyright messages

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

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