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

1.1       anton       1: /* signal handling
                      2: 
1.27      anton       3:   Copyright (C) 1995,1996,1997,1998,2000,2003 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> */
1.20      anton      34: #include <sys/types.h>
1.2       anton      35: #include <signal.h>
1.1       anton      36: #include "io.h"
                     37: 
1.20      anton      38: #ifndef HAVE_STACK_T
                     39: /* Darwin uses "struct sigaltstack" instead of "stack_t" */
                     40: typedef struct sigaltstack stack_t;
                     41: #endif
1.1       anton      42: 
                     43: #define DEFAULTCOLS 80
                     44: #if defined(MSDOS) || defined (_WIN32)
                     45: #define DEFAULTROWS 25
                     46: #else
                     47: #define DEFAULTROWS 24
                     48: #endif
                     49: 
                     50: UCell cols=DEFAULTCOLS;
                     51: UCell rows=DEFAULTROWS;
                     52: 
1.7       anton      53: #ifndef SA_NODEFER
1.8       anton      54: #define SA_NODEFER 0
1.7       anton      55: /* systems that don't have SA_NODEFER hopefully don't block anyway */
                     56: #endif
                     57: 
1.17      anton      58: #ifndef SA_ONSTACK
                     59: #define SA_ONSTACK 0
                     60: #endif
                     61: 
1.5       anton      62: #ifdef SA_SIGINFO
                     63: void install_signal_handler(int sig, void (*handler)(int, siginfo_t *, void *))
                     64:      /* installs three-argument signal handler for sig */
                     65: {
                     66:   struct sigaction action;
                     67: 
                     68:   action.sa_sigaction=handler;
                     69:   sigemptyset(&action.sa_mask);
1.15      anton      70:   action.sa_flags=SA_RESTART|SA_NODEFER|SA_SIGINFO|SA_ONSTACK; /* pass siginfo */
1.5       anton      71:   sigaction(sig, &action, NULL);
                     72: }
                     73: #endif
                     74: 
                     75: Sigfunc *bsd_signal(int signo, Sigfunc *func)
                     76: {
                     77:   struct sigaction act, oact;
                     78: 
                     79:   act.sa_handler=func;
                     80:   sigemptyset(&act.sa_mask);
1.18      anton      81:   act.sa_flags=SA_NODEFER; /* SA_ONSTACK does not work for graceful_exit */
1.5       anton      82:   if (sigaction(signo,&act,&oact) < 0)
                     83:     return SIG_ERR;
                     84:   else
                     85:     return oact.sa_handler;
                     86: }
1.1       anton      87: 
                     88: static void
                     89: graceful_exit (int sig)
                     90: {
                     91:   deprep_terminal();
                     92:   fprintf (stderr, "\n\n%s.\n", strsignal (sig));
                     93:   exit (0x80|sig);
                     94: }
                     95: 
                     96: jmp_buf throw_jmp_buf;
                     97: 
                     98: static void 
                     99: signal_throw(int sig)
                    100: {
                    101:   int code;
1.3       anton     102: 
                    103:   switch (sig) {
                    104:   case SIGINT: code=-28; break;
                    105:   case SIGFPE: code=-55; break;
1.1       anton     106: #ifdef SIGBUS
1.3       anton     107:   case SIGBUS: code=-23; break;
1.1       anton     108: #endif
1.3       anton     109:   case SIGSEGV: code=-9; break;
1.25      anton     110: #ifdef SIGPIPE
                    111:   case SIGPIPE: code=-2049; break;
                    112: #endif
1.3       anton     113:   default: code=-256-sig; break;
                    114:   }
1.26      anton     115: #ifdef __CYGWIN__
                    116:   /* the SA_NODEFER apparently does not work on Cygwin 1.3.18(0.69/3/2) */
                    117:   {
                    118:     sigset_t emptyset;
                    119:     sigemptyset(&emptyset);
                    120:     sigprocmask(SIG_SETMASK, &emptyset, NULL);
                    121:   }
                    122: #endif
1.3       anton     123:   longjmp(throw_jmp_buf,code); /* !! or use siglongjmp ? */
                    124: }
                    125: 
                    126: #ifdef SA_SIGINFO
1.24      anton     127: static void
                    128: sigaction_throw(int sig, siginfo_t *info, void *_)
                    129: {
                    130:   signal_throw(sig);
                    131: }
                    132: 
1.3       anton     133: static void fpe_handler(int sig, siginfo_t *info, void *_)
                    134:      /* handler for SIGFPE */
                    135: {
                    136:   int code;
                    137: 
                    138:   switch(info->si_code) {
1.16      anton     139: #ifdef FPE_INTDIV
1.3       anton     140:   case FPE_INTDIV: code=-10; break; /* integer divide by zero */
1.16      anton     141: #endif
                    142: #ifdef FPE_INTOVF
1.3       anton     143:   case FPE_INTOVF: code=-11; break; /* integer overflow */
1.16      anton     144: #endif
1.28      anton     145: #ifdef FPE_FLTDIV
1.3       anton     146:   case FPE_FLTDIV: code=-42; break; /* floating point divide by zero */
1.28      anton     147: #endif
                    148: #ifdef FPE_FLTOVF
1.3       anton     149:   case FPE_FLTOVF: code=-43; break; /* floating point overflow  */
1.28      anton     150: #endif
                    151: #ifdef FPE_FLTUND
1.3       anton     152:   case FPE_FLTUND: code=-54; break; /* floating point underflow  */
1.28      anton     153: #endif
                    154: #ifdef FPE_FLTRES
1.3       anton     155:   case FPE_FLTRES: code=-41; break; /* floating point inexact result  */
1.28      anton     156: #endif
1.16      anton     157: #if 0 /* defined by Unix95, but unnecessary */
1.3       anton     158:   case FPE_FLTINV: /* invalid floating point operation  */
                    159:   case FPE_FLTSUB: /* subscript out of range  */
1.16      anton     160: #endif
1.3       anton     161:   default: code=-55; break;
                    162:   }
                    163:   longjmp(throw_jmp_buf,code);
                    164: }
                    165: 
                    166: 
                    167: #define SPILLAGE 128
                    168: /* if there's a SIGSEGV within SPILLAGE bytes of some stack, we assume
                    169:    that this stack has over/underflowed */
                    170: 
                    171: #define JUSTUNDER(addr1,addr2) (((UCell)((addr2)-1-(addr1)))<SPILLAGE)
                    172: /* true is addr1 is just under addr2 */
                    173: 
                    174: #define JUSTOVER(addr1,addr2) (((UCell)((addr1)-(addr2)))<SPILLAGE)
                    175: 
                    176: #define NEXTPAGE(addr) ((Address)((((UCell)(addr)-1)&-pagesize)+pagesize))
                    177: 
                    178: static void segv_handler(int sig, siginfo_t *info, void *_)
                    179: {
                    180:   int code=-9;
                    181:   Address addr=info->si_addr;
                    182:   ImageHeader *h=gforth_header;
                    183: 
                    184:   if (JUSTUNDER(addr, h->data_stack_base))
                    185:     code=-3;
                    186:   else if (JUSTOVER(addr, NEXTPAGE(h->data_stack_base+h->data_stack_size)))
                    187:     code=-4;
                    188:   else if (JUSTUNDER(addr, h->return_stack_base))
                    189:     code=-5;
                    190:   else if (JUSTOVER(addr, NEXTPAGE(h->return_stack_base+h->return_stack_size)))
                    191:     code=-6;
                    192:   else if (JUSTUNDER(addr, h->fp_stack_base))
                    193:     code=-44;
                    194:   else if (JUSTOVER(addr, NEXTPAGE(h->fp_stack_base+h->fp_stack_size)))
                    195:     code=-45;
                    196:   longjmp(throw_jmp_buf,code);
1.1       anton     197: }
                    198: 
1.3       anton     199: #endif /* defined(SA_SIGINFO) */
                    200: 
1.1       anton     201: #ifdef SIGCONT
1.9       anton     202: static void termprep(int sig)
1.1       anton     203: {
1.5       anton     204:   bsd_signal(sig,termprep);
1.1       anton     205:   terminal_prepped=0;
                    206: }
                    207: #endif
                    208: 
                    209: void get_winsize()
                    210: {
                    211: #ifdef TIOCGWINSZ
                    212:   struct winsize size;
1.12      pazsan    213:   size.ws_row = size.ws_col = 0;
1.1       anton     214:   
                    215:   if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {
                    216:     rows = size.ws_row;
                    217:     cols = size.ws_col;
                    218:   }
                    219: #else
                    220:   char *s;
                    221:   if ((s=getenv("LINES"))) {
                    222:     rows=atoi(s);
                    223:   }
                    224:   if ((s=getenv("COLUMNS"))) {
                    225:     rows=atoi(s);
                    226:   }
                    227: #endif
1.12      pazsan    228:   if (rows==0)
                    229:     rows=DEFAULTROWS;
                    230:   if (rows==0)
                    231:     cols=DEFAULTCOLS;
1.1       anton     232: }
                    233: 
                    234: #ifdef SIGWINCH
                    235: static void change_winsize(int sig)
                    236: {
1.5       anton     237:   /* signal(sig,change_winsize); should not be necessary with bsd_signal */
1.1       anton     238: #ifdef TIOCGWINSZ
                    239:   get_winsize();
                    240: #endif
                    241: }
                    242: #endif
                    243: 
1.2       anton     244: void install_signal_handlers(void)
1.1       anton     245: {
                    246: 
                    247: #if 0
                    248: /* these signals are handled right by default, no need to handle them;
                    249:    they are listed here just for fun */
                    250:   static short sigs_to_default [] = {
                    251: #ifdef SIGCHLD
                    252:     SIGCHLD,
                    253: #endif
                    254: #ifdef SIGINFO
                    255:     SIGINFO,
                    256: #endif
                    257: #ifdef SIGIO
                    258:     SIGIO,
                    259: #endif
                    260: #ifdef SIGLOST
                    261:     SIGLOST,
                    262: #endif
                    263: #ifdef SIGKILL
                    264:     SIGKILL,
                    265: #endif
                    266: #ifdef SIGSTOP
                    267:     SIGSTOP,
                    268: #endif
                    269: #ifdef SIGPWR
                    270:     SIGPWR,
                    271: #endif
                    272: #ifdef SIGMSG
                    273:     SIGMSG,
                    274: #endif
                    275: #ifdef SIGDANGER
                    276:     SIGDANGER,
                    277: #endif
                    278: #ifdef SIGMIGRATE
                    279:     SIGMIGRATE,
                    280: #endif
                    281: #ifdef SIGPRE
                    282:     SIGPRE,
                    283: #endif
                    284: #ifdef SIGVIRT
                    285:     SIGVIRT,
                    286: #endif
                    287: #ifdef SIGGRANT
                    288:     SIGGRANT,
                    289: #endif
                    290: #ifdef SIGRETRACT
                    291:     SIGRETRACT,
                    292: #endif
                    293: #ifdef SIGSOUND
                    294:     SIGSOUND,
                    295: #endif
                    296: #ifdef SIGSAK
                    297:     SIGSAK,
                    298: #endif
                    299: #ifdef SIGTSTP
                    300:     SIGTSTP,
                    301: #endif
                    302: #ifdef SIGTTIN
                    303:     SIGTTIN,
                    304: #endif
                    305: #ifdef SIGTTOU
                    306:     SIGTTOU,
                    307: #endif
                    308: #ifdef SIGSTKFLT
                    309:     SIGSTKFLT,
                    310: #endif
                    311: #ifdef SIGUNUSED
                    312:     SIGUNUSED,
                    313: #endif
                    314:   };
                    315: #endif
                    316: 
1.30    ! anton     317:   static short async_sigs_to_throw [] = {
        !           318: #ifdef SIGINT
        !           319:     SIGINT,
        !           320: #endif
        !           321: #ifdef SIGALRM
        !           322:     SIGALRM,
        !           323: #endif
        !           324: #ifdef SIGPOLL
        !           325:     SIGPOLL,
        !           326: #endif
        !           327: #ifdef SIGPROF
        !           328:     SIGPROF,
        !           329: #endif
        !           330: #ifdef SIGURG
        !           331:     SIGURG,
        !           332: #endif
        !           333: #ifdef SIGPIPE
        !           334:     SIGPIPE,
        !           335: #endif
        !           336: #ifdef SIGUSR1
        !           337:     SIGUSR1,
        !           338: #endif
        !           339: #ifdef SIGUSR2
        !           340:     SIGUSR2,
        !           341: #endif
        !           342: #ifdef SIGVTALRM
        !           343:     SIGVTALRM,
        !           344: #endif
        !           345: #ifdef SIGXFSZ
        !           346:     SIGXFSZ,
        !           347: #endif
        !           348:   };
        !           349: 
1.1       anton     350:   static short sigs_to_throw [] = {
                    351: #ifdef SIGBREAK
                    352:     SIGBREAK,
                    353: #endif
                    354: #ifdef SIGILL
                    355:     SIGILL,
                    356: #endif
                    357: #ifdef SIGEMT
                    358:     SIGEMT,
                    359: #endif
                    360: #ifdef SIGFPE
                    361:     SIGFPE,
                    362: #endif
                    363: #ifdef SIGIOT
                    364:     SIGIOT,
                    365: #endif
                    366: #ifdef SIGSEGV
                    367:     SIGSEGV,
                    368: #endif
                    369: #ifdef SIGBUS
                    370:     SIGBUS,
                    371: #endif
                    372: #ifdef SIGSYS
                    373:     SIGSYS,
                    374: #endif
                    375: #ifdef SIGTRAP
                    376:     SIGTRAP,
                    377: #endif
                    378:   };
1.30    ! anton     379: 
1.1       anton     380:   static short sigs_to_quit [] = {
1.4       pazsan    381: #ifdef SIGQUIT
                    382:     SIGQUIT,
                    383: #endif
1.1       anton     384: #ifdef SIGHUP
                    385:     SIGHUP,
                    386: #endif
                    387: #ifdef SIGABRT
                    388:     SIGABRT,
                    389: #endif
                    390: #ifdef SIGTERM
                    391:     SIGTERM,
                    392: #endif
                    393: #ifdef SIGXCPU
                    394:     SIGXCPU,
                    395: #endif
                    396:   };
                    397:   int i;
1.2       anton     398:   void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
1.17      anton     399: #ifdef SIGSTKSZ 
1.15      anton     400:   stack_t sigstack;
                    401:   int sas_retval=-1;
                    402: 
                    403:   sigstack.ss_size=SIGSTKSZ;
1.23      anton     404:   /* Actually the stack should only be ss_size large, and according to
                    405:      SUSv2 ss_sp should point to the start of the stack, but
                    406:      unfortunately Irix 6.5 (at least) expects ss_sp to point to the
                    407:      end, so we work around this issue by accomodating everyone. */
1.29      pazsan    408:   if ((sigstack.ss_sp = gforth_alloc(sigstack.ss_size*2)) != NULL) {
1.23      anton     409:     sigstack.ss_sp += sigstack.ss_size;
1.15      anton     410:     sigstack.ss_flags=0;
                    411:     sas_retval=sigaltstack(&sigstack,(stack_t *)0);
                    412:   }
                    413:   if (debug)
                    414:     fprintf(stderr,"sigaltstack: %s\n",strerror(sas_retval));
1.17      anton     415: #endif
1.1       anton     416: 
                    417: #define DIM(X)         (sizeof (X) / sizeof *(X))
                    418: /*
                    419:   for (i = 0; i < DIM (sigs_to_ignore); i++)
                    420:     signal (sigs_to_ignore [i], SIG_IGN);
                    421: */
                    422:   for (i = 0; i < DIM (sigs_to_throw); i++)
1.5       anton     423:     bsd_signal(sigs_to_throw[i], throw_handler);
1.30    ! anton     424:   for (i = 0; i < DIM (async_sigs_to_throw); i++)
        !           425:     bsd_signal(async_sigs_to_throw[i], 
        !           426:                ignore_async_signals ? SIG_IGN : throw_handler);
1.1       anton     427:   for (i = 0; i < DIM (sigs_to_quit); i++)
1.5       anton     428:     bsd_signal(sigs_to_quit [i], graceful_exit);
1.3       anton     429: #ifdef SA_SIGINFO
1.14      anton     430:   if (!die_on_signal) {
1.24      anton     431: #ifdef SIGFPE
1.14      anton     432:     install_signal_handler(SIGFPE, fpe_handler);
1.24      anton     433: #endif
                    434: #ifdef SIGSEGV
1.14      anton     435:     install_signal_handler(SIGSEGV, segv_handler);
1.24      anton     436: #endif
                    437:     /* use SA_ONSTACK for all signals that could come from executing
                    438:        wrong code */
                    439: #ifdef SIGILL
                    440:     install_signal_handler(SIGILL, sigaction_throw);
                    441: #endif
                    442: #ifdef SIGBUS
                    443:     install_signal_handler(SIGBUS, sigaction_throw);
                    444: #endif
                    445: #ifdef SIGTRAP
                    446:     install_signal_handler(SIGTRAP, sigaction_throw);
                    447: #endif
1.14      anton     448:   }
1.24      anton     449: #endif /* defined(SA_SIGINFO) */
1.1       anton     450: #ifdef SIGCONT
1.5       anton     451:     bsd_signal(SIGCONT, termprep);
1.1       anton     452: #endif
                    453: #ifdef SIGWINCH
1.5       anton     454:     bsd_signal(SIGWINCH, change_winsize);
1.1       anton     455: #endif
                    456: }

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