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

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: 
                     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
1.2       anton      33: /* #include <asm/signal.h> */
                     34: #include <signal.h>
1.1       anton      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: 
1.7       anton      50: #ifndef SA_NODEFER
1.8       anton      51: #define SA_NODEFER 0
1.7       anton      52: /* systems that don't have SA_NODEFER hopefully don't block anyway */
                     53: #endif
                     54: 
1.17      anton      55: #ifndef SA_ONSTACK
                     56: #define SA_ONSTACK 0
                     57: #endif
                     58: 
1.5       anton      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);
1.15      anton      67:   action.sa_flags=SA_RESTART|SA_NODEFER|SA_SIGINFO|SA_ONSTACK; /* pass siginfo */
1.5       anton      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);
1.18    ! anton      80:   act.sa_flags=SA_NODEFER; /* SA_ONSTACK does not work for graceful_exit */
1.5       anton      81:   if (sigaction(signo,&act,&oact) < 0)
                     82:     return SIG_ERR;
                     83:   else
                     84:     return oact.sa_handler;
                     85: }
1.1       anton      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;
1.3       anton     101: 
                    102:   switch (sig) {
                    103:   case SIGINT: code=-28; break;
                    104:   case SIGFPE: code=-55; break;
1.1       anton     105: #ifdef SIGBUS
1.3       anton     106:   case SIGBUS: code=-23; break;
1.1       anton     107: #endif
1.3       anton     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) {
1.16      anton     121: #ifdef FPE_INTDIV
1.3       anton     122:   case FPE_INTDIV: code=-10; break; /* integer divide by zero */
1.16      anton     123: #endif
                    124: #ifdef FPE_INTOVF
1.3       anton     125:   case FPE_INTOVF: code=-11; break; /* integer overflow */
1.16      anton     126: #endif
1.3       anton     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  */
1.16      anton     131: #if 0 /* defined by Unix95, but unnecessary */
1.3       anton     132:   case FPE_FLTINV: /* invalid floating point operation  */
                    133:   case FPE_FLTSUB: /* subscript out of range  */
1.16      anton     134: #endif
1.3       anton     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);
1.1       anton     171: }
                    172: 
1.3       anton     173: #endif /* defined(SA_SIGINFO) */
                    174: 
1.1       anton     175: #ifdef SIGCONT
1.9       anton     176: static void termprep(int sig)
1.1       anton     177: {
1.5       anton     178:   bsd_signal(sig,termprep);
1.1       anton     179:   terminal_prepped=0;
                    180: }
                    181: #endif
                    182: 
                    183: void get_winsize()
                    184: {
                    185: #ifdef TIOCGWINSZ
                    186:   struct winsize size;
1.12      pazsan    187:   size.ws_row = size.ws_col = 0;
1.1       anton     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
1.12      pazsan    202:   if (rows==0)
                    203:     rows=DEFAULTROWS;
                    204:   if (rows==0)
                    205:     cols=DEFAULTCOLS;
1.1       anton     206: }
                    207: 
                    208: #ifdef SIGWINCH
                    209: static void change_winsize(int sig)
                    210: {
1.5       anton     211:   /* signal(sig,change_winsize); should not be necessary with bsd_signal */
1.1       anton     212: #ifdef TIOCGWINSZ
                    213:   get_winsize();
                    214: #endif
                    215: }
                    216: #endif
                    217: 
1.2       anton     218: void install_signal_handlers(void)
1.1       anton     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 [] = {
1.4       pazsan    351: #ifdef SIGQUIT
                    352:     SIGQUIT,
                    353: #endif
1.1       anton     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;
1.2       anton     368:   void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
1.17      anton     369: #ifdef SIGSTKSZ 
1.15      anton     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));
1.17      anton     380: #endif
1.1       anton     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++)
1.5       anton     388:     bsd_signal(sigs_to_throw[i], throw_handler);
1.1       anton     389:   for (i = 0; i < DIM (sigs_to_quit); i++)
1.5       anton     390:     bsd_signal(sigs_to_quit [i], graceful_exit);
1.3       anton     391: #ifdef SA_SIGINFO
1.14      anton     392:   if (!die_on_signal) {
                    393:     install_signal_handler(SIGFPE, fpe_handler);
                    394:     install_signal_handler(SIGSEGV, segv_handler);
                    395:   }
1.3       anton     396: #endif
1.1       anton     397: #ifdef SIGCONT
1.5       anton     398:     bsd_signal(SIGCONT, termprep);
1.1       anton     399: #endif
                    400: #ifdef SIGWINCH
1.5       anton     401:     bsd_signal(SIGWINCH, change_winsize);
1.1       anton     402: #endif
                    403: }

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