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

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

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