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

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

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