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