2
unixint.c -- Unix interrupt interface.
5
Copyright (c) 1984, Taiichi Yuasa and Masami Hagiya.
6
Copyright (c) 1990, Giuseppe Attardi.
7
Copyright (c) 2001, Juan Jose Garcia Ripoll.
9
ECL is free software; you can redistribute it and/or
10
modify it under the terms of the GNU Library General Public
11
License as published by the Free Software Foundation; either
12
version 2 of the License, or (at your option) any later version.
14
See file '../Copyright' for full details.
18
#if defined(HAVE_FENV_H)
22
# define FE_UNDERFLOW 0
25
# define FE_OVERFLOW 0
31
# define FE_DIVBYZERO 0
38
#if defined(mingw32) || defined(_MSC_VER)
40
void handle_fpe_signal(int,int);
42
#if !defined(_MSC_VER)
45
#include <ecl/internal.h>
47
/******************************* ------- ******************************/
49
bool ecl_interrupt_enable;
51
#ifdef HAVE_SIGPROCMASK
53
mysignal(int code, void *handler)
55
struct sigaction new_action, old_action;
57
new_action.sa_sigaction = handler;
58
sigemptyset(&new_action.sa_mask);
59
new_action.sa_flags = SA_SIGINFO;
60
sigaction(code, &new_action, &old_action);
63
#define mysignal(x,y) signal(x,y)
68
handle_signal(int sig, siginfo_t *info, void *aux)
70
handle_signal(int sig)
74
#if defined(ECL_THREADS) && !defined(_MSC_VER) && !defined(mingw32)
76
funcall(1, cl_env.own_process->process.interrupt);
80
funcall(2, @'si::terminal-interrupt', Ct);
83
cl_object condition = @'arithmetic-error';
84
#if defined(HAVE_FENV_H)
85
int bits = fetestexcept(FE_ALL_EXCEPT);
86
if (bits & FE_DIVBYZERO)
87
condition = @'division-by-zero';
88
if (bits & FE_OVERFLOW)
89
condition = @'floating-point-overflow';
90
if (bits & FE_UNDERFLOW)
91
condition = @'floating-point-underflow';
92
if (bits & FE_INEXACT)
93
condition = @'floating-point-inexact';
94
if (bits & FE_INVALID)
95
condition = @'floating-point-invalid-operation';
99
if (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)
100
condition = @'division-by-zero';
101
if (info->si_code == FPE_FLTOVF)
102
condition = @'floating-point-overflow';
103
if (info->si_code == FPE_FLTUND)
104
condition = @'floating-point-underflow';
107
si_trap_fpe(@'last', Ct);
108
cl_error(1, condition);
112
FEerror("Segmentation violation.", 0);
115
FEerror("Serious signal ~D caught.", 1, MAKE_FIXNUM(sig));
120
* TODO: Use POSIX signals, and in particular use sigaltstack to
121
* handle stack overflows gracefully.
125
signal_catcher(int sig, siginfo_t *siginfo, void *data)
127
signal_catcher(int sig)
130
if (!ecl_interrupt_enable ||
131
symbol_value(@'si::*interrupt-enable*') == Cnil) {
132
mysignal(sig, signal_catcher);
133
cl_env.interrupt_pending = sig;
136
mysignal(sig, signal_catcher);
137
#ifdef HAVE_SIGPROCMASK
138
CL_UNWIND_PROTECT_BEGIN {
139
handle_signal(sig, siginfo, data);
140
} CL_UNWIND_PROTECT_EXIT {
142
sigemptyset(&block_mask);
143
sigaddset(&block_mask, sig);
145
pthread_sigmask(SIG_UNBLOCK, &block_mask, NULL);
147
sigprocmask(SIG_UNBLOCK, &block_mask, NULL);
149
} CL_UNWIND_PROTECT_END;
151
#if defined (_MSC_VER)
153
handle_fpe_signal(sig, _fpecode);
161
si_check_pending_interrupts(void)
163
int what = cl_env.interrupt_pending;
164
cl_env.interrupt_pending = 0;
165
#ifdef HAVE_SIGPROCMASK
166
handle_signal(what, 0, 0);
174
si_catch_bad_signals()
176
mysignal(SIGILL, signal_catcher);
178
mysignal(SIGBUS, signal_catcher);
180
mysignal(SIGSEGV, signal_catcher);
182
mysignal(SIGIOT, signal_catcher);
185
mysignal(SIGEMT, signal_catcher);
188
mysignal(SIGSYS, signal_catcher);
194
si_uncatch_bad_signals()
196
mysignal(SIGILL, SIG_DFL);
198
mysignal(SIGBUS, SIG_DFL);
200
mysignal(SIGSEGV, SIG_DFL);
202
mysignal(SIGIOT, SIG_DFL);
205
mysignal(SIGEMT, SIG_DFL);
208
mysignal(SIGSYS, SIG_DFL);
214
LONG WINAPI W32_exception_filter(struct _EXCEPTION_POINTERS* ep)
218
excpt_result = EXCEPTION_CONTINUE_EXECUTION;
219
switch (ep->ExceptionRecord->ExceptionCode)
221
/* Catch all arithmetic exceptions */
222
case EXCEPTION_INT_DIVIDE_BY_ZERO:
223
case EXCEPTION_INT_OVERFLOW:
224
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
225
case EXCEPTION_FLT_OVERFLOW:
226
case EXCEPTION_FLT_UNDERFLOW:
227
case EXCEPTION_FLT_INEXACT_RESULT:
228
case EXCEPTION_FLT_DENORMAL_OPERAND:
229
case EXCEPTION_FLT_INVALID_OPERATION:
230
case EXCEPTION_FLT_STACK_CHECK:
231
handle_signal(SIGFPE);
233
/* Catch segmentation fault */
234
case EXCEPTION_ACCESS_VIOLATION:
235
handle_signal(SIGSEGV);
237
/* Catch illegal instruction */
238
case EXCEPTION_ILLEGAL_INSTRUCTION:
239
handle_signal(SIGILL);
241
/* Do not catch anything else */
243
excpt_result = EXCEPTION_CONTINUE_SEARCH;
250
void handle_fpe_signal(int sig, int num)
252
cl_object condition = @'arithmetic-error';
256
condition = @'floating-point-overflow';
259
condition = @'floating-point-underflow';
261
case _FPE_ZERODIVIDE:
262
condition = @'division-by-zero';
266
si_trap_fpe(@'last', Ct);
267
cl_error(1, condition);
270
BOOL WINAPI W32_console_ctrl_handler(DWORD type)
276
handle_signal(SIGINT);
284
si_trap_fpe(cl_object condition, cl_object flag)
286
#if (defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)) || defined(_MSC_VER) || defined(mingw32)
287
static int last_bits = 0;
289
if (condition == @'division-by-zero')
291
else if (condition == @'floating-point-overflow')
293
else if (condition == @'floating-point-underflow')
295
else if (condition == Ct)
296
bits = FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW;
297
else if (condition == @'last')
299
#if defined(_MSC_VER) || defined(mingw32)
304
fedisableexcept(bits);
307
feenableexcept(bits);
318
mysignal(SIGFPE, signal_catcher);
320
mysignal(SIGINT, signal_catcher);
321
#if defined(ECL_THREADS) && !defined(_MSC_VER) && !defined(mingw32)
322
mysignal(SIGUSR1, signal_catcher);
325
SetUnhandledExceptionFilter(W32_exception_filter);
326
SetConsoleCtrlHandler(W32_console_ctrl_handler, TRUE);
328
ECL_SET(@'si::*interrupt-enable*', Ct);
329
ecl_interrupt_enable = 1;