File:
[gforth] /
gforth /
engine /
signals.c
Revision
1.19:
download - view:
text,
annotated -
select for diffs
Tue Dec 24 23:40:30 2002 UTC (21 years, 4 months ago) by
anton
Branches:
MAIN
CVS tags:
HEAD
Gforth now supports large files (>2GB) on small machines (32-bits/cell).
forth.h now asks for all kinds of POSIX, X/Open, and GNU support.
rearranged include files such that forth.h precedes the system files.
1: /* signal handling
2:
3: Copyright (C) 1995,1996,1997,1998,2000 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., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20:
21: */
22:
23:
24: #include "config.h"
25: #include "forth.h"
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
33: /* #include <asm/signal.h> */
34: #include <signal.h>
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:
48: #ifndef SA_NODEFER
49: #define SA_NODEFER 0
50: /* systems that don't have SA_NODEFER hopefully don't block anyway */
51: #endif
52:
53: #ifndef SA_ONSTACK
54: #define SA_ONSTACK 0
55: #endif
56:
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);
65: action.sa_flags=SA_RESTART|SA_NODEFER|SA_SIGINFO|SA_ONSTACK; /* pass siginfo */
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);
78: act.sa_flags=SA_NODEFER; /* SA_ONSTACK does not work for graceful_exit */
79: if (sigaction(signo,&act,&oact) < 0)
80: return SIG_ERR;
81: else
82: return oact.sa_handler;
83: }
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;
99:
100: switch (sig) {
101: case SIGINT: code=-28; break;
102: case SIGFPE: code=-55; break;
103: #ifdef SIGBUS
104: case SIGBUS: code=-23; break;
105: #endif
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) {
119: #ifdef FPE_INTDIV
120: case FPE_INTDIV: code=-10; break; /* integer divide by zero */
121: #endif
122: #ifdef FPE_INTOVF
123: case FPE_INTOVF: code=-11; break; /* integer overflow */
124: #endif
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 */
129: #if 0 /* defined by Unix95, but unnecessary */
130: case FPE_FLTINV: /* invalid floating point operation */
131: case FPE_FLTSUB: /* subscript out of range */
132: #endif
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);
169: }
170:
171: #endif /* defined(SA_SIGINFO) */
172:
173: #ifdef SIGCONT
174: static void termprep(int sig)
175: {
176: bsd_signal(sig,termprep);
177: terminal_prepped=0;
178: }
179: #endif
180:
181: void get_winsize()
182: {
183: #ifdef TIOCGWINSZ
184: struct winsize size;
185: size.ws_row = size.ws_col = 0;
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
200: if (rows==0)
201: rows=DEFAULTROWS;
202: if (rows==0)
203: cols=DEFAULTCOLS;
204: }
205:
206: #ifdef SIGWINCH
207: static void change_winsize(int sig)
208: {
209: /* signal(sig,change_winsize); should not be necessary with bsd_signal */
210: #ifdef TIOCGWINSZ
211: get_winsize();
212: #endif
213: }
214: #endif
215:
216: void install_signal_handlers(void)
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 [] = {
349: #ifdef SIGQUIT
350: SIGQUIT,
351: #endif
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;
366: void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
367: #ifdef SIGSTKSZ
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));
378: #endif
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++)
386: bsd_signal(sigs_to_throw[i], throw_handler);
387: for (i = 0; i < DIM (sigs_to_quit); i++)
388: bsd_signal(sigs_to_quit [i], graceful_exit);
389: #ifdef SA_SIGINFO
390: if (!die_on_signal) {
391: install_signal_handler(SIGFPE, fpe_handler);
392: install_signal_handler(SIGSEGV, segv_handler);
393: }
394: #endif
395: #ifdef SIGCONT
396: bsd_signal(SIGCONT, termprep);
397: #endif
398: #ifdef SIGWINCH
399: bsd_signal(SIGWINCH, change_winsize);
400: #endif
401: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>