Annotation of gforth/engine/signals.c, revision 1.19

1.1       anton       1: /* signal handling
                      2: 
1.10      anton       3:   Copyright (C) 1995,1996,1997,1998,2000 Free Software Foundation, Inc.
1.1       anton       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
1.11      anton      19:   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
1.1       anton      20: 
                     21: */
                     22: 
                     23: 
1.19    ! anton      24: #include "config.h"
        !            25: #include "forth.h"
1.1       anton      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
1.2       anton      33: /* #include <asm/signal.h> */
                     34: #include <signal.h>
1.1       anton      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: 
1.7       anton      48: #ifndef SA_NODEFER
1.8       anton      49: #define SA_NODEFER 0
1.7       anton      50: /* systems that don't have SA_NODEFER hopefully don't block anyway */
                     51: #endif
                     52: 
1.17      anton      53: #ifndef SA_ONSTACK
                     54: #define SA_ONSTACK 0
                     55: #endif
                     56: 
1.5       anton      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);
1.15      anton      65:   action.sa_flags=SA_RESTART|SA_NODEFER|SA_SIGINFO|SA_ONSTACK; /* pass siginfo */
1.5       anton      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);
1.18      anton      78:   act.sa_flags=SA_NODEFER; /* SA_ONSTACK does not work for graceful_exit */
1.5       anton      79:   if (sigaction(signo,&act,&oact) < 0)
                     80:     return SIG_ERR;
                     81:   else
                     82:     return oact.sa_handler;
                     83: }
1.1       anton      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;
1.3       anton      99: 
                    100:   switch (sig) {
                    101:   case SIGINT: code=-28; break;
                    102:   case SIGFPE: code=-55; break;
1.1       anton     103: #ifdef SIGBUS
1.3       anton     104:   case SIGBUS: code=-23; break;
1.1       anton     105: #endif
1.3       anton     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) {
1.16      anton     119: #ifdef FPE_INTDIV
1.3       anton     120:   case FPE_INTDIV: code=-10; break; /* integer divide by zero */
1.16      anton     121: #endif
                    122: #ifdef FPE_INTOVF
1.3       anton     123:   case FPE_INTOVF: code=-11; break; /* integer overflow */
1.16      anton     124: #endif
1.3       anton     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  */
1.16      anton     129: #if 0 /* defined by Unix95, but unnecessary */
1.3       anton     130:   case FPE_FLTINV: /* invalid floating point operation  */
                    131:   case FPE_FLTSUB: /* subscript out of range  */
1.16      anton     132: #endif
1.3       anton     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);
1.1       anton     169: }
                    170: 
1.3       anton     171: #endif /* defined(SA_SIGINFO) */
                    172: 
1.1       anton     173: #ifdef SIGCONT
1.9       anton     174: static void termprep(int sig)
1.1       anton     175: {
1.5       anton     176:   bsd_signal(sig,termprep);
1.1       anton     177:   terminal_prepped=0;
                    178: }
                    179: #endif
                    180: 
                    181: void get_winsize()
                    182: {
                    183: #ifdef TIOCGWINSZ
                    184:   struct winsize size;
1.12      pazsan    185:   size.ws_row = size.ws_col = 0;
1.1       anton     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
1.12      pazsan    200:   if (rows==0)
                    201:     rows=DEFAULTROWS;
                    202:   if (rows==0)
                    203:     cols=DEFAULTCOLS;
1.1       anton     204: }
                    205: 
                    206: #ifdef SIGWINCH
                    207: static void change_winsize(int sig)
                    208: {
1.5       anton     209:   /* signal(sig,change_winsize); should not be necessary with bsd_signal */
1.1       anton     210: #ifdef TIOCGWINSZ
                    211:   get_winsize();
                    212: #endif
                    213: }
                    214: #endif
                    215: 
1.2       anton     216: void install_signal_handlers(void)
1.1       anton     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 [] = {
1.4       pazsan    349: #ifdef SIGQUIT
                    350:     SIGQUIT,
                    351: #endif
1.1       anton     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;
1.2       anton     366:   void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
1.17      anton     367: #ifdef SIGSTKSZ 
1.15      anton     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));
1.17      anton     378: #endif
1.1       anton     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++)
1.5       anton     386:     bsd_signal(sigs_to_throw[i], throw_handler);
1.1       anton     387:   for (i = 0; i < DIM (sigs_to_quit); i++)
1.5       anton     388:     bsd_signal(sigs_to_quit [i], graceful_exit);
1.3       anton     389: #ifdef SA_SIGINFO
1.14      anton     390:   if (!die_on_signal) {
                    391:     install_signal_handler(SIGFPE, fpe_handler);
                    392:     install_signal_handler(SIGSEGV, segv_handler);
                    393:   }
1.3       anton     394: #endif
1.1       anton     395: #ifdef SIGCONT
1.5       anton     396:     bsd_signal(SIGCONT, termprep);
1.1       anton     397: #endif
                    398: #ifdef SIGWINCH
1.5       anton     399:     bsd_signal(SIGWINCH, change_winsize);
1.1       anton     400: #endif
                    401: }

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