1.0.26.15: interrupt.c refactoring
[sbcl.git] / src / runtime / interr.c
index a5f8650..3b0a882 100644 (file)
 
 #include <stdio.h>
 #include <stdarg.h>
+#include <stdlib.h>
 
+#include "sbcl.h"
 #include "arch.h"
 #include "signal.h"
 
 #include "runtime.h"
-#include "sbcl.h"
 #include "interr.h"
 #include "print.h"
 #include "lispregs.h"
+#include "genesis/static-symbols.h"
+#include "genesis/vector.h"
+#include "thread.h"
+#include "monitor.h"
 \f
 /* the way that we shut down the system on a fatal error */
 
@@ -33,29 +38,84 @@ default_lossage_handler(void)
     exit(1);
 }
 static void (*lossage_handler)(void) = default_lossage_handler;
-void
-set_lossage_handler(void handler(void))
+
+void enable_lossage_handler(void)
 {
-    lossage_handler = handler;
+    lossage_handler = monitor_or_something;
+}
+void disable_lossage_handler(void)
+{
+    lossage_handler = default_lossage_handler;
 }
 
-never_returns
-lose(char *fmt, ...)
+static
+void print_message(char *fmt, va_list ap)
 {
-    va_list ap;
-    fprintf(stderr, "fatal error encountered in SBCL runtime system");
+    fprintf(stderr, " in SBCL pid %d",getpid());
+#if defined(LISP_FEATURE_SB_THREAD)
+    fprintf(stderr, "(tid %lu)", (unsigned long) thread_self());
+#endif
     if (fmt) {
-       fprintf(stderr, ":\n");
-       va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
-       va_end(ap);
+        fprintf(stderr, ":\n");
+        vfprintf(stderr, fmt, ap);
     }
     fprintf(stderr, "\n");
-    fflush(stderr);
+}
+
+static inline void
+call_lossage_handler() never_returns;
+
+static inline void
+call_lossage_handler()
+{
     lossage_handler();
     fprintf(stderr, "Argh! lossage_handler() returned, total confusion..\n");
     exit(1);
 }
+
+void
+lose(char *fmt, ...)
+{
+    va_list ap;
+    /* Block signals to prevent other threads, timers and such from
+     * interfering. If only all threads could be stopped somehow. */
+    block_blockable_signals(0, 0);
+    fprintf(stderr, "fatal error encountered");
+    va_start(ap, fmt);
+    print_message(fmt, ap);
+    va_end(ap);
+    fprintf(stderr, "\n");
+    fflush(stderr);
+    call_lossage_handler();
+}
+
+boolean lose_on_corruption_p = 0;
+
+void
+corruption_warning_and_maybe_lose(char *fmt, ...)
+{
+    va_list ap;
+#ifndef LISP_FEATURE_WIN32
+    sigset_t oldset;
+    block_blockable_signals(0, &oldset);
+#endif
+    fprintf(stderr, "CORRUPTION WARNING");
+    va_start(ap, fmt);
+    print_message(fmt, ap);
+    va_end(ap);
+    fprintf(stderr, "The integrity of this image is possibly compromised.\n");
+    if (lose_on_corruption_p)
+        fprintf(stderr, "Exiting.\n");
+    else
+        fprintf(stderr, "Continuing with fingers crossed.\n");
+    fflush(stderr);
+    if (lose_on_corruption_p)
+        call_lossage_handler();
+#ifndef LISP_FEATURE_WIN32
+    else
+        thread_sigmask(SIG_SETMASK,&oldset,0);
+#endif
+}
 \f
 /* internal error handler for when the Lisp error system doesn't exist
  *
@@ -72,79 +132,79 @@ describe_internal_error(os_context_t *context)
     printf("internal error #%d\n", *ptr++);
     len--;
     while (len > 0) {
-       scoffset = *ptr++;
-       len--;
-       if (scoffset == 253) {
-           scoffset = *ptr++;
-           len--;
-       }
-       else if (scoffset == 254) {
-           scoffset = ptr[0] + ptr[1]*256;
-           ptr += 2;
-           len -= 2;
-       }
-       else if (scoffset == 255) {
-           scoffset = ptr[0] + (ptr[1]<<8) + (ptr[2]<<16) + (ptr[3]<<24);
-           ptr += 4;
-           len -= 4;
-       }
-       sc = scoffset & 0x1f;
-       offset = scoffset >> 5;
-               
-       printf("    SC: %d, Offset: %d", sc, offset);
-       switch (sc) {
-       case sc_AnyReg:
-       case sc_DescriptorReg:
-           putchar('\t');
-           brief_print(*os_context_register_addr(context, offset));
-           break;
-
-       case sc_BaseCharReg:
-           ch = *os_context_register_addr(context, offset);
-#ifdef __i386__
-           if (offset&1)
-               ch = ch>>8;
-           ch = ch & 0xff;
+        scoffset = *ptr++;
+        len--;
+        if (scoffset == 253) {
+            scoffset = *ptr++;
+            len--;
+        }
+        else if (scoffset == 254) {
+            scoffset = ptr[0] + ptr[1]*256;
+            ptr += 2;
+            len -= 2;
+        }
+        else if (scoffset == 255) {
+            scoffset = ptr[0] + (ptr[1]<<8) + (ptr[2]<<16) + (ptr[3]<<24);
+            ptr += 4;
+            len -= 4;
+        }
+        sc = scoffset & 0x1f;
+        offset = scoffset >> 5;
+
+        printf("    SC: %d, Offset: %d", sc, offset);
+        switch (sc) {
+        case sc_AnyReg:
+        case sc_DescriptorReg:
+            putchar('\t');
+            brief_print(*os_context_register_addr(context, offset));
+            break;
+
+        case sc_CharacterReg:
+            ch = *os_context_register_addr(context, offset);
+#ifdef LISP_FEATURE_X86
+            if (offset&1)
+                ch = ch>>8;
+            ch = ch & 0xff;
 #endif
-           switch (ch) {
-           case '\n': printf("\t'\\n'\n"); break;
-           case '\b': printf("\t'\\b'\n"); break;
-           case '\t': printf("\t'\\t'\n"); break;
-           case '\r': printf("\t'\\r'\n"); break;
-           default:
-               if (ch < 32 || ch > 127)
-                   printf("\\%03o", ch);
-               else
-                   printf("\t'%c'\n", ch);
-               break;
-           }
-           break;
-       case sc_SapReg:
+            switch (ch) {
+            case '\n': printf("\t'\\n'\n"); break;
+            case '\b': printf("\t'\\b'\n"); break;
+            case '\t': printf("\t'\\t'\n"); break;
+            case '\r': printf("\t'\\r'\n"); break;
+            default:
+                if (ch < 32 || ch > 127)
+                    printf("\\%03o", ch);
+                else
+                    printf("\t'%c'\n", ch);
+                break;
+            }
+            break;
+        case sc_SapReg:
 #ifdef sc_WordPointerReg
-       case sc_WordPointerReg:
+        case sc_WordPointerReg:
 #endif
-           printf("\t0x%08x\n", *os_context_register_addr(context, offset));
-           break;
-       case sc_SignedReg:
-           printf("\t%d\n", *os_context_register_addr(context, offset));
-           break;
-       case sc_UnsignedReg:
-           printf("\t%u\n", *os_context_register_addr(context, offset));
-           break;
+            printf("\t0x%08lx\n", (unsigned long) *os_context_register_addr(context, offset));
+            break;
+        case sc_SignedReg:
+            printf("\t%ld\n", (long) *os_context_register_addr(context, offset));
+            break;
+        case sc_UnsignedReg:
+            printf("\t%lu\n", (unsigned long) *os_context_register_addr(context, offset));
+            break;
 #ifdef sc_SingleFloatReg
-       case sc_SingleFloatReg:
-           printf("\t%g\n", *(float *)&context->sc_fpregs[offset]);
-           break;
+        case sc_SingleFloatReg:
+            printf("\t%g\n", *(float *)&context->sc_fpregs[offset]);
+            break;
 #endif
 #ifdef sc_DoubleFloatReg
-       case sc_DoubleFloatReg:
-           printf("\t%g\n", *(double *)&context->sc_fpregs[offset]);
-           break;
+        case sc_DoubleFloatReg:
+            printf("\t%g\n", *(double *)&context->sc_fpregs[offset]);
+            break;
 #endif
-       default:
-           printf("\t???\n");
-           break;
-       }
+        default:
+            printf("\t???\n");
+            break;
+        }
     }
 }
 \f
@@ -152,16 +212,19 @@ describe_internal_error(os_context_t *context)
 
 lispobj debug_print(lispobj string)
 {
-    /* This is a kludge.  It's not actually safe - in general - to use 
+    /* This is a kludge.  It's not actually safe - in general - to use
        %primitive print on the alpha, because it skips half of the
-       number stack setup that should usually be done on a function call,
-       so the called routine (i.e. this one) ends up being able to overwrite
-       local variables in the caller.  Rather than fix this everywhere
-       that %primitive print is used (it's only a debugging aid anyway)
-       we just put guarantee our safety by putting an unused buffer on
-       the stack before doing anything else here */
-    char untouched[32]; /* GCC warns about not using this, but that's the point.. */
-    fprintf(stderr, "%s\n", 
-           (char *)(((struct vector *)native_pointer(string))->data),untouched);
+       number stack setup that should usually be done on a function
+       call, so the called routine (i.e. this one) ends up being able
+       to overwrite local variables in the caller.  Rather than fix
+       this everywhere that %primitive print is used (it's only a
+       debugging aid anyway) we just guarantee our safety by putting
+       an unused buffer on the stack before doing anything else
+       here */
+    char untouched[32];
+    fprintf(stderr, "%s\n",
+            (char *)(((struct vector *)native_pointer(string))->data));
+    /* shut GCC up about not using this, because that's the point.. */
+    (void)untouched;
     return NIL;
 }