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

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

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