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