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