File:  [gforth] / gforth / engine / signals.c
Revision 1.13: download - view: text, annotated - select for diffs
Sat Jan 5 22:59:00 2002 UTC (22 years, 2 months ago) by pazsan
Branches: MAIN
CVS tags: HEAD
Thrown out static vocabulary stack
Changed cross to make mixed threading workable

    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:   size.ws_row = size.ws_col = 0;
  178:   
  179:   if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {
  180:     rows = size.ws_row;
  181:     cols = size.ws_col;
  182:   }
  183: #else
  184:   char *s;
  185:   if ((s=getenv("LINES"))) {
  186:     rows=atoi(s);
  187:   }
  188:   if ((s=getenv("COLUMNS"))) {
  189:     rows=atoi(s);
  190:   }
  191: #endif
  192:   if (rows==0)
  193:     rows=DEFAULTROWS;
  194:   if (rows==0)
  195:     cols=DEFAULTCOLS;
  196: }
  197: 
  198: #ifdef SIGWINCH
  199: static void change_winsize(int sig)
  200: {
  201:   /* signal(sig,change_winsize); should not be necessary with bsd_signal */
  202: #ifdef TIOCGWINSZ
  203:   get_winsize();
  204: #endif
  205: }
  206: #endif
  207: 
  208: void install_signal_handlers(void)
  209: {
  210: 
  211: #if 0
  212: /* these signals are handled right by default, no need to handle them;
  213:    they are listed here just for fun */
  214:   static short sigs_to_default [] = {
  215: #ifdef SIGCHLD
  216:     SIGCHLD,
  217: #endif
  218: #ifdef SIGINFO
  219:     SIGINFO,
  220: #endif
  221: #ifdef SIGIO
  222:     SIGIO,
  223: #endif
  224: #ifdef SIGLOST
  225:     SIGLOST,
  226: #endif
  227: #ifdef SIGKILL
  228:     SIGKILL,
  229: #endif
  230: #ifdef SIGSTOP
  231:     SIGSTOP,
  232: #endif
  233: #ifdef SIGPWR
  234:     SIGPWR,
  235: #endif
  236: #ifdef SIGMSG
  237:     SIGMSG,
  238: #endif
  239: #ifdef SIGDANGER
  240:     SIGDANGER,
  241: #endif
  242: #ifdef SIGMIGRATE
  243:     SIGMIGRATE,
  244: #endif
  245: #ifdef SIGPRE
  246:     SIGPRE,
  247: #endif
  248: #ifdef SIGVIRT
  249:     SIGVIRT,
  250: #endif
  251: #ifdef SIGGRANT
  252:     SIGGRANT,
  253: #endif
  254: #ifdef SIGRETRACT
  255:     SIGRETRACT,
  256: #endif
  257: #ifdef SIGSOUND
  258:     SIGSOUND,
  259: #endif
  260: #ifdef SIGSAK
  261:     SIGSAK,
  262: #endif
  263: #ifdef SIGTSTP
  264:     SIGTSTP,
  265: #endif
  266: #ifdef SIGTTIN
  267:     SIGTTIN,
  268: #endif
  269: #ifdef SIGTTOU
  270:     SIGTTOU,
  271: #endif
  272: #ifdef SIGSTKFLT
  273:     SIGSTKFLT,
  274: #endif
  275: #ifdef SIGUNUSED
  276:     SIGUNUSED,
  277: #endif
  278:   };
  279: #endif
  280: 
  281:   static short sigs_to_throw [] = {
  282: #ifdef SIGBREAK
  283:     SIGBREAK,
  284: #endif
  285: #ifdef SIGINT
  286:     SIGINT,
  287: #endif
  288: #ifdef SIGILL
  289:     SIGILL,
  290: #endif
  291: #ifdef SIGEMT
  292:     SIGEMT,
  293: #endif
  294: #ifdef SIGFPE
  295:     SIGFPE,
  296: #endif
  297: #ifdef SIGIOT
  298:     SIGIOT,
  299: #endif
  300: #ifdef SIGSEGV
  301:     SIGSEGV,
  302: #endif
  303: #ifdef SIGALRM
  304:     SIGALRM,
  305: #endif
  306: #ifdef SIGPIPE
  307:     SIGPIPE,
  308: #endif
  309: #ifdef SIGPOLL
  310:     SIGPOLL,
  311: #endif
  312: #ifdef SIGPROF
  313:     SIGPROF,
  314: #endif
  315: #ifdef SIGBUS
  316:     SIGBUS,
  317: #endif
  318: #ifdef SIGSYS
  319:     SIGSYS,
  320: #endif
  321: #ifdef SIGTRAP
  322:     SIGTRAP,
  323: #endif
  324: #ifdef SIGURG
  325:     SIGURG,
  326: #endif
  327: #ifdef SIGUSR1
  328:     SIGUSR1,
  329: #endif
  330: #ifdef SIGUSR2
  331:     SIGUSR2,
  332: #endif
  333: #ifdef SIGVTALRM
  334:     SIGVTALRM,
  335: #endif
  336: #ifdef SIGXFSZ
  337:     SIGXFSZ,
  338: #endif
  339:   };
  340:   static short sigs_to_quit [] = {
  341: #ifdef SIGQUIT
  342:     SIGQUIT,
  343: #endif
  344: #ifdef SIGHUP
  345:     SIGHUP,
  346: #endif
  347: #ifdef SIGABRT
  348:     SIGABRT,
  349: #endif
  350: #ifdef SIGTERM
  351:     SIGTERM,
  352: #endif
  353: #ifdef SIGXCPU
  354:     SIGXCPU,
  355: #endif
  356:   };
  357:   int i;
  358:   void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
  359: 
  360: #define DIM(X)		(sizeof (X) / sizeof *(X))
  361: /*
  362:   for (i = 0; i < DIM (sigs_to_ignore); i++)
  363:     signal (sigs_to_ignore [i], SIG_IGN);
  364: */
  365:   for (i = 0; i < DIM (sigs_to_throw); i++)
  366:     bsd_signal(sigs_to_throw[i], throw_handler);
  367:   for (i = 0; i < DIM (sigs_to_quit); i++)
  368:     bsd_signal(sigs_to_quit [i], graceful_exit);
  369: #ifdef SA_SIGINFO
  370:   install_signal_handler(SIGFPE, die_on_signal ? graceful_exit : fpe_handler);
  371:   install_signal_handler(SIGSEGV, die_on_signal ? graceful_exit : segv_handler);
  372: #endif
  373: #ifdef SIGCONT
  374:     bsd_signal(SIGCONT, termprep);
  375: #endif
  376: #ifdef SIGWINCH
  377:     bsd_signal(SIGWINCH, change_winsize);
  378: #endif
  379: }

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