Annotation of gforth/engine/signals.c, revision 1.12
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.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
1.9 anton 166: static void termprep(int sig)
1.1 anton 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;
1.12 ! pazsan 177: size.ws_row = size.ws_col = 0;
1.1 anton 178:
179: if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {
180: rows = size.ws_row;
181: cols = size.ws_col;
182: }
183: #else
184: char *s;
185: if ((s=getenv("LINES"))) {
186: rows=atoi(s);
187: }
188: if ((s=getenv("COLUMNS"))) {
189: rows=atoi(s);
190: }
191: #endif
1.12 ! pazsan 192: if (rows==0)
! 193: rows=DEFAULTROWS;
! 194: if (rows==0)
! 195: cols=DEFAULTCOLS;
1.1 anton 196: }
197:
198: #ifdef SIGWINCH
199: static void change_winsize(int sig)
200: {
1.5 anton 201: /* signal(sig,change_winsize); should not be necessary with bsd_signal */
1.1 anton 202: #ifdef TIOCGWINSZ
203: get_winsize();
204: #endif
205: }
206: #endif
207:
1.2 anton 208: void install_signal_handlers(void)
1.1 anton 209: {
210:
211: #if 0
212: /* these signals are handled right by default, no need to handle them;
213: they are listed here just for fun */
214: static short sigs_to_default [] = {
215: #ifdef SIGCHLD
216: SIGCHLD,
217: #endif
218: #ifdef SIGINFO
219: SIGINFO,
220: #endif
221: #ifdef SIGIO
222: SIGIO,
223: #endif
224: #ifdef SIGLOST
225: SIGLOST,
226: #endif
227: #ifdef SIGKILL
228: SIGKILL,
229: #endif
230: #ifdef SIGSTOP
231: SIGSTOP,
232: #endif
233: #ifdef SIGPWR
234: SIGPWR,
235: #endif
236: #ifdef SIGMSG
237: SIGMSG,
238: #endif
239: #ifdef SIGDANGER
240: SIGDANGER,
241: #endif
242: #ifdef SIGMIGRATE
243: SIGMIGRATE,
244: #endif
245: #ifdef SIGPRE
246: SIGPRE,
247: #endif
248: #ifdef SIGVIRT
249: SIGVIRT,
250: #endif
251: #ifdef SIGGRANT
252: SIGGRANT,
253: #endif
254: #ifdef SIGRETRACT
255: SIGRETRACT,
256: #endif
257: #ifdef SIGSOUND
258: SIGSOUND,
259: #endif
260: #ifdef SIGSAK
261: SIGSAK,
262: #endif
263: #ifdef SIGTSTP
264: SIGTSTP,
265: #endif
266: #ifdef SIGTTIN
267: SIGTTIN,
268: #endif
269: #ifdef SIGTTOU
270: SIGTTOU,
271: #endif
272: #ifdef SIGSTKFLT
273: SIGSTKFLT,
274: #endif
275: #ifdef SIGUNUSED
276: SIGUNUSED,
277: #endif
278: };
279: #endif
280:
281: static short sigs_to_throw [] = {
282: #ifdef SIGBREAK
283: SIGBREAK,
284: #endif
285: #ifdef SIGINT
286: SIGINT,
287: #endif
288: #ifdef SIGILL
289: SIGILL,
290: #endif
291: #ifdef SIGEMT
292: SIGEMT,
293: #endif
294: #ifdef SIGFPE
295: SIGFPE,
296: #endif
297: #ifdef SIGIOT
298: SIGIOT,
299: #endif
300: #ifdef SIGSEGV
301: SIGSEGV,
302: #endif
303: #ifdef SIGALRM
304: SIGALRM,
305: #endif
306: #ifdef SIGPIPE
307: SIGPIPE,
308: #endif
309: #ifdef SIGPOLL
310: SIGPOLL,
311: #endif
312: #ifdef SIGPROF
313: SIGPROF,
314: #endif
315: #ifdef SIGBUS
316: SIGBUS,
317: #endif
318: #ifdef SIGSYS
319: SIGSYS,
320: #endif
321: #ifdef SIGTRAP
322: SIGTRAP,
323: #endif
324: #ifdef SIGURG
325: SIGURG,
326: #endif
327: #ifdef SIGUSR1
328: SIGUSR1,
329: #endif
330: #ifdef SIGUSR2
331: SIGUSR2,
332: #endif
333: #ifdef SIGVTALRM
334: SIGVTALRM,
335: #endif
336: #ifdef SIGXFSZ
337: SIGXFSZ,
338: #endif
339: };
340: static short sigs_to_quit [] = {
1.4 pazsan 341: #ifdef SIGQUIT
342: SIGQUIT,
343: #endif
1.1 anton 344: #ifdef SIGHUP
345: SIGHUP,
346: #endif
347: #ifdef SIGABRT
348: SIGABRT,
349: #endif
350: #ifdef SIGTERM
351: SIGTERM,
352: #endif
353: #ifdef SIGXCPU
354: SIGXCPU,
355: #endif
356: };
357: int i;
1.2 anton 358: void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
1.1 anton 359:
360: #define DIM(X) (sizeof (X) / sizeof *(X))
361: /*
362: for (i = 0; i < DIM (sigs_to_ignore); i++)
363: signal (sigs_to_ignore [i], SIG_IGN);
364: */
365: for (i = 0; i < DIM (sigs_to_throw); i++)
1.5 anton 366: bsd_signal(sigs_to_throw[i], throw_handler);
1.1 anton 367: for (i = 0; i < DIM (sigs_to_quit); i++)
1.5 anton 368: bsd_signal(sigs_to_quit [i], graceful_exit);
1.3 anton 369: #ifdef SA_SIGINFO
370: install_signal_handler(SIGFPE, fpe_handler);
371: install_signal_handler(SIGSEGV, segv_handler);
372: #endif
1.1 anton 373: #ifdef SIGCONT
1.5 anton 374: bsd_signal(SIGCONT, termprep);
1.1 anton 375: #endif
376: #ifdef SIGWINCH
1.5 anton 377: bsd_signal(SIGWINCH, change_winsize);
1.1 anton 378: #endif
379: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>