1.0.47.3: better DEFSTRUCT constructor type declarations
[sbcl.git] / src / code / cold-error.lisp
index 4295160..ba9bfae 100644 (file)
                                         'simple-condition
                                         'signal))
         (*handler-clusters* *handler-clusters*)
-        (old-bos *break-on-signals*))
+        (old-bos *break-on-signals*)
+        (bos-actually-breaking nil))
     (restart-case
-        (when (typep condition *break-on-signals*)
-          (let ((*break-on-signals* nil))
+        (let ((break-on-signals *break-on-signals*)
+              (*break-on-signals* nil))
+          ;; The rebinding encloses the TYPEP so that a bogus
+          ;; type specifier will not lead to infinite recursion when
+          ;; TYPEP fails.
+          (when (typep condition break-on-signals)
+            (setf bos-actually-breaking t)
             (break "~A~%BREAK was entered because of *BREAK-ON-SIGNALS* ~
                     (now rebound to NIL)."
                    condition)))
       ;; unless we provide this restart.)
       (reassign (new-value)
         :report
-        "Return from BREAK and assign a new value to *BREAK-ON-SIGNALS*."
+        (lambda (stream)
+          (format stream
+                  (if bos-actually-breaking
+                    "Return from BREAK and assign a new value to ~
+                     *BREAK-ON-SIGNALS*."
+                    "Assign a new value to *BREAK-ON-SIGNALS* and ~
+                     continue with signal handling.")))
         :interactive
         (lambda ()
           (let (new-value)
 
   (infinite-error-protect
     (let ((condition (coerce-to-condition datum arguments
-                                          'simple-error 'error))
-          (sb!debug:*stack-top-hint* (maybe-find-stack-top-hint)))
+                                          'simple-error 'error)))
       (/show0 "done coercing DATUM to CONDITION")
+      (/show0 "signalling CONDITION from within ERROR")
       (let ((sb!debug:*stack-top-hint* nil))
-        (/show0 "signalling CONDITION from within ERROR")
         (signal condition))
       (/show0 "done signalling CONDITION within ERROR")
-      (invoke-debugger condition))))
+      ;; Finding the stack top hint is pretty expensive, so don't do
+      ;; it until we know we need the debugger.
+      (let ((sb!debug:*stack-top-hint* (maybe-find-stack-top-hint)))
+        (invoke-debugger condition)))))
 
 (defun cerror (continue-string datum &rest arguments)
   (infinite-error-protect
       (let ((condition (coerce-to-condition datum
                                             arguments
                                             'simple-error
-                                            'cerror))
-            (sb!debug:*stack-top-hint* (maybe-find-stack-top-hint)))
+                                            'cerror)))
         (with-condition-restarts condition (list (find-restart 'continue))
           (let ((sb!debug:*stack-top-hint* nil))
             (signal condition))
-          (invoke-debugger condition)))))
+          (let ((sb!debug:*stack-top-hint* (maybe-find-stack-top-hint)))
+            (invoke-debugger condition))))))
   nil)
 
 ;;; like BREAK, but without rebinding *DEBUGGER-HOOK* to NIL, so that