/* SysExceptions.c configure the signals to create m2 exceptions. Copyright (C) 2009-2022 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include #if defined(HAVE_SIGNAL_H) #include #endif #if defined(HAVE_ERRNO_H) #include #endif #if defined(HAVE_SYS_ERRNO_H) #include #endif #if defined(HAVE_STDIO_H) #include #endif #include "m2rts.h" #if 0 /* Signals. */ #define SIGHUP 1 /* Hangup (POSIX). */ #define SIGINT 2 /* Interrupt (ANSI). */ #define SIGQUIT 3 /* Quit (POSIX). */ #define SIGILL 4 /* Illegal instruction (ANSI). */ #define SIGTRAP 5 /* Trace trap (POSIX). */ #define SIGABRT 6 /* Abort (ANSI). */ #define SIGIOT 6 /* IOT trap (4.2 BSD). */ #define SIGBUS 7 /* BUS error (4.2 BSD). */ #define SIGFPE 8 /* Floating-point exception (ANSI). */ #define SIGKILL 9 /* Kill, unblockable (POSIX). */ #define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ #define SIGSEGV 11 /* Segmentation violation (ANSI). */ #define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ #define SIGPIPE 13 /* Broken pipe (POSIX). */ #define SIGALRM 14 /* Alarm clock (POSIX). */ #define SIGTERM 15 /* Termination (ANSI). */ #define SIGSTKFLT 16 /* Stack fault. */ #define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ #define SIGCHLD 17 /* Child status has changed (POSIX). */ #define SIGCONT 18 /* Continue (POSIX). */ #define SIGSTOP 19 /* Stop, unblockable (POSIX). */ #define SIGTSTP 20 /* Keyboard stop (POSIX). */ #define SIGTTIN 21 /* Background read from tty (POSIX). */ #define SIGTTOU 22 /* Background write to tty (POSIX). */ #define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ #define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ #define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ #define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ #define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ #define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ #define SIGPOLL SIGIO /* Pollable event occurred (System V). */ #define SIGIO 29 /* I/O now possible (4.2 BSD). */ #define SIGPWR 30 /* Power failure restart (System V). */ #define SIGSYS 31 /* Bad system call. */ #define SIGUNUSED 31 /* The list of Modula-2 exceptions is shown below */ (indexException, rangeException, caseSelectException, invalidLocation, functionException, wholeValueException, wholeDivException, realValueException, realDivException, complexValueException, complexDivException, protException, sysException, coException, exException ); #endif /* Note: wholeDivException and realDivException are caught by SIGFPE and depatched to the appropriate Modula-2 runtime routine upon testing FPE_INTDIV or FPE_FLTDIV. realValueException is also caught by SIGFPE and dispatched by testing FFE_FLTOVF or FPE_FLTUND or FPE_FLTRES or FPE_FLTINV. indexException is caught by SIGFPE and dispatched by FPE_FLTSUB. */ #if defined(HAVE_SIGNAL_H) static struct sigaction sigbus; static struct sigaction sigfpe; static struct sigaction sigsegv; static void (*indexProc) (void *); static void (*rangeProc) (void *); static void (*assignmentrangeProc) (void *); static void (*caseProc) (void *); static void (*invalidlocProc) (void *); static void (*functionProc) (void *); static void (*wholevalueProc) (void *); static void (*wholedivProc) (void *); static void (*realvalueProc) (void *); static void (*realdivProc) (void *); static void (*complexvalueProc) (void *); static void (*complexdivProc) (void *); static void (*protectionProc) (void *); static void (*systemProc) (void *); static void (*coroutineProc) (void *); static void (*exceptionProc) (void *); static void sigbusDespatcher (int signum, siginfo_t *info, void *ucontext) { switch (signum) { case SIGSEGV: case SIGBUS: if (info) (*invalidlocProc) (info->si_addr); break; default: perror ("not expecting to arrive here with this signal"); } } static void sigfpeDespatcher (int signum, siginfo_t *info, void *ucontext) { switch (signum) { case SIGFPE: if (info) { if (info->si_code | FPE_INTDIV) (*wholedivProc) (info->si_addr); /* Integer divide by zero. */ if (info->si_code | FPE_INTOVF) (*wholevalueProc) (info->si_addr); /* Integer overflow. */ if (info->si_code | FPE_FLTDIV) (*realdivProc) (info->si_addr); /* Floating-point divide by zero. */ if (info->si_code | FPE_FLTOVF) (*realvalueProc) (info->si_addr); /* Floating-point overflow. */ if (info->si_code | FPE_FLTUND) (*realvalueProc) (info->si_addr); /* Floating-point underflow. */ if (info->si_code | FPE_FLTRES) (*realvalueProc) ( info->si_addr); /* Floating-point inexact result. */ if (info->si_code | FPE_FLTINV) (*realvalueProc) ( info->si_addr); /* Floating-point invalid result. */ if (info->si_code | FPE_FLTSUB) (*indexProc) (info->si_addr); /* Subscript out of range. */ } break; default: perror ("not expecting to arrive here with this signal"); } } extern "C" void SysExceptions_InitExceptionHandlers ( void (*indexf) (void *), void (*range) (void *), void (*casef) (void *), void (*invalidloc) (void *), void (*function) (void *), void (*wholevalue) (void *), void (*wholediv) (void *), void (*realvalue) (void *), void (*realdiv) (void *), void (*complexvalue) (void *), void (*complexdiv) (void *), void (*protection) (void *), void (*systemf) (void *), void (*coroutine) (void *), void (*exception) (void *)) { struct sigaction old; indexProc = indexf; rangeProc = range; caseProc = casef; invalidlocProc = invalidloc; functionProc = function; wholevalueProc = wholevalue; wholedivProc = wholediv; realvalueProc = realvalue; realdivProc = realdiv; complexvalueProc = complexvalue; complexdivProc = complexdiv; protectionProc = protection; systemProc = systemf; coroutineProc = coroutine; exceptionProc = exception; sigbus.sa_sigaction = sigbusDespatcher; sigbus.sa_flags = (SA_SIGINFO); sigemptyset (&sigbus.sa_mask); if (sigaction (SIGBUS, &sigbus, &old) != 0) perror ("unable to install the sigbus signal handler"); sigsegv.sa_sigaction = sigbusDespatcher; sigsegv.sa_flags = (SA_SIGINFO); sigemptyset (&sigsegv.sa_mask); if (sigaction (SIGSEGV, &sigsegv, &old) != 0) perror ("unable to install the sigsegv signal handler"); sigfpe.sa_sigaction = sigfpeDespatcher; sigfpe.sa_flags = (SA_SIGINFO); sigemptyset (&sigfpe.sa_mask); if (sigaction (SIGFPE, &sigfpe, &old) != 0) perror ("unable to install the sigfpe signal handler"); } #else extern "C" void SysExceptions_InitExceptionHandlers (void *indexf, void *range, void *casef, void *invalidloc, void *function, void *wholevalue, void *wholediv, void *realvalue, void *realdiv, void *complexvalue, void *complexdiv, void *protection, void *systemf, void *coroutine, void *exception) { } #endif extern "C" void _M2_SysExceptions_init (int, char *[], char *[]) { } extern "C" void _M2_SysExceptions_fini (int, char *[], char *[]) { } extern "C" void _M2_SysExceptions_dep (void) { } extern "C" void __attribute__((__constructor__)) _M2_SysExceptions_ctor (void) { M2RTS_RegisterModule ("SysExceptions", _M2_SysExceptions_init, _M2_SysExceptions_fini, _M2_SysExceptions_dep); }