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