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