[project @ 1997-11-24 21:09:55 by sof]
[ghc-hetmet.git] / ghc / runtime / main / Signals.lc
index 1b1af46..f473cae 100644 (file)
@@ -31,7 +31,7 @@ much pain.
 # define NON_POSIX_SOURCE
 #endif
 
-#if defined(freebsd_TARGET_OS)
+#if defined(freebsd_TARGET_OS) 
 # define NON_POSIX_SOURCE
 #endif
 
@@ -121,16 +121,21 @@ Fun, eh?
 
 \begin{code}
 # if defined(sunos4_TARGET_OS) || defined(freebsd_TARGET_OS) \
-  || defined(linux_TARGET_OS)  || defined(linuxaout_TARGET_OS)
+  || defined(linux_TARGET_OS)  || defined(linuxaout_TARGET_OS) \
+  || defined(aix_TARGET_OS)
 
 static void
 segv_handler(int sig,
     /* NB: all except first argument are "implementation defined" */
 #  if defined(sunos4_TARGET_OS) || defined(freebsd_TARGET_OS)
        int code, struct sigcontext *scp, caddr_t addr)
-#  else /* linux */
+#  else /* linux || aix */
+#    if defined(aix_TARGET_OS)
+       int code, struct sigcontext *scp)
+#    else /* linux */
        struct sigcontext_struct scp)
-#  endif /* linux */
+#    endif 
+#  endif
 {
     extern void StackOverflow(STG_NO_ARGS) STG_NORETURN;
 
@@ -138,7 +143,10 @@ segv_handler(int sig,
     caddr_t addr = scp.cr2;
     /* Magic info from Tommy Thorn! */
 #  endif
-
+#  if defined(aix_TARGET_OS)
+    caddr_t addr = scp->sc_jmpbuf.jmp_context.o_vaddr;
+    /* Magic guess by andre */
+#  endif
     if (addr >= (caddr_t) stks_space
       && addr < (caddr_t) (stks_space + RTSflags.GcFlags.stksSize))
        StackOverflow();
@@ -155,7 +163,9 @@ install_segv_handler(void)
     /* FreeBSD seems to generate SIGBUS for stack overflows */
     if (signal(SIGBUS, segv_handler) == SIG_ERR)
        return -1;
-    return ((int) signal(SIGSEGV, segv_handler));
+    if (signal(SIGSEGV, segv_handler) == SIG_ERR)
+       return -1;
+    return 0;
 #else
     return ((int) signal(SIGSEGV, segv_handler) == SIG_ERR);
     /* I think the "== SIG_ERR" is saying "there was no
@@ -164,33 +174,60 @@ install_segv_handler(void)
 #endif
 }
 
-# else /* Not SunOS 4, FreeBSD, or Linux(a.out) */
+# elif defined(irix6_TARGET_OS)
 
-#  if defined(irix_TARGET_OS)
-     /* certainly BOGUS (WDP 94/05) -- copied from /usr/include/sys/siginfo.h */
-#   define si_addr _data._fault._addr
-#  endif
+static void
+segv_handler(int sig, siginfo_t *sip, void *dummy)
+{
+    fflush(stdout);
+    if (sip == NULL) {
+       fprintf(stderr, "Segmentation fault caught, address unknown\n");
+    } else {
+       if (sip->si_addr >= (void *) stks_space
+         && sip->si_addr < (void *) (stks_space + RTSflags.GcFlags.stksSize))
+           StackOverflow();
+       fprintf(stderr, "Segmentation fault caught, address = %08lx\n", (W_) sip->si_addr);
+    }
+    abort();
+}
+
+int
+install_segv_handler(STG_NO_ARGS)
+{
+    struct sigaction action;
+
+    action.sa_sigaction = segv_handler;
+    sigemptyset(&action.sa_mask);
+    action.sa_flags = SA_SIGINFO;
+
+    return sigaction(SIGSEGV, &action, NULL);
+}
+
+# elif defined(cygwin32_TARGET_OS)
 
-#if defined(cygwin32_TARGET_OS)
 /*
- The signal handlers in cygwin32 (beta14) are only passed the signal
+ The signal handlers in cygwin32  are only passed the signal
  number, no sigcontext/siginfo is passed as event data..sigh. For
  SIGSEGV, to get at the violating address, we need to use the Win32's
- WaitForDebugEvent() to get out any status information. 
+ GetThreadContext() to get at the faulting address.
 */
 static void
 segv_handler(sig)
  int sig;
 {
-    /* From gdb/win32-nat.c */
-    DEBUG_EVENT event;
-    BOOL t = WaitForDebugEvent (&event, INFINITE);
+    CONTEXT context;
+    HANDLE hThread;
+    BOOL t;
+
+    context.ContextFlags = CONTEXT_CONTROL;
+    hThread = GetCurrentThread(); /* cannot fail */
+    t = GetThreadContext(hThread,&context);
 
     fflush(stdout);
     if (t == FALSE) {
         fprintf(stderr, "Segmentation fault caught, address unknown\n");
     } else {
-        void *si_addr = event.u.Exception.ExceptionRecord.ExceptionAddress;
+        void *si_addr = context.Eip; /* magic */
         if (si_addr >= (void *) stks_space
           && si_addr < (void *) (stks_space + RTSflags.GcFlags.stksSize))
             StackOverflow();
@@ -206,8 +243,12 @@ install_segv_handler()
     return (int) signal(SIGSEGV, segv_handler) == -1;
 }
 
+# else /* ! (cygwin32|irix6|sunos4|linux*|*bsd|aix) */
 
-#else /* !defined(cygwin32_TARGET_OS) */
+#  if defined(irix_TARGET_OS)
+        /* certainly BOGUS (WDP 94/05) -- copied from /usr/include/sys/siginfo.h */
+#     define si_addr _data._fault._addr
+#  endif
 
 static void
 segv_handler(int sig, siginfo_t *sip)
@@ -238,9 +279,7 @@ install_segv_handler(STG_NO_ARGS)
     return sigaction(SIGSEGV, &action, NULL);
 }
 
-#endif /* not cygwin32_TARGET_OS */
-
-# endif    /* not SunOS 4 */
+# endif /* ! (cygwin32|irix6|sunos4|linux*|*bsd|aix) */
 
 #endif /* STACK_CHECK_BY_PAGE_FAULT */