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