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