318: "stack overflow in compiler warning with redefined class"
reported by Bruno Haible sbcl-devel "various SBCL bugs" from CLISP
test suite.
- (setq *print-pretty* nil)
(defstruct foo a)
(setf (find-class 'foo) nil)
(defstruct foo slot-1)
- gives
- ...#<SB-KERNEL:STRUCTURE-CLASSOID #<SB-KERNEL:STRUCTURE-CLASSOID #<SB-KERNEL:STRUCTURE-CLASSOID #<SB-KERNEL:STRUCTUREControl stack guard page temporarily disabled: proceed with caution
- (it's not really clear what it should give: is (SETF FIND-CLASS)
- meant to be enough to delete structure classes from the system?
- Giving a stack overflow is definitely suboptimal, though.)
+ This used to give a stack overflow from within the printer, which has
+ been fixed as of 0.8.16.11. Current result:
+ ; caught ERROR:
+ ; can't compile TYPEP of anonymous or undefined class:
+ ; #<SB-KERNEL:STRUCTURE-CLASSOID FOO>
+ ...
+ debugger invoked on a TYPE-ERROR in thread 19973:
+ The value NIL is not of type FUNCTION.
+
+ CSR notes: it's not really clear what it should give: is (SETF FIND-CLASS)
+ meant to be enough to delete structure classes from the system?
319: "backquote with comma inside array"
reported by Bruno Haible sbcl-devel "various SBCL bugs" from CLISP
changes in sbcl-0.8.17 relative to sbcl-0.8.16:
* minor incompatible change: BASE-CHAR no longer names a class;
however, CHARACTER continues to do so, as required by ANSI.
+ * minor incompatible change: SB-DEBUG:*DEBUG-PRINT-FOO* variables
+ are no longer supported, and SB-DEBUG:*DEBUG-PRINT-VARIABLE-ALIST*
+ has been moved to the SB-EXT package (temporarily re-exported from
+ SB-DEBUG).
+ * minor incompatible change: SB-C::*COMPILER-ERROR-PRINT-FOO* variables
+ are no longer supported: use SB-EXT:*COMPILER-PRINT-VARIABLE-ALIST*
+ instead.
+ * bug fix: Cyclic structures and unprintable objects in compiler
+ messages no longer cause errors. (reported by Bruno Haible)
* bug fix: READ, READ-PRESERVING-WHITESPACE, READ-DELIMITED-LIST,
and READ-FROM-STRING all now return a primary value of NIL if
*READ-SUPPRESS* is true. (reported by Bruno Haible for CMUCL)
declaration.
@end deffn
+Various details of @emph{how} the compiler messages are printed can be
+controlled via the alist
+@code{sb-ext:*compiler-print-variable-alist*}.
+
+@include var-sb-ext-star-compiler-print-variable-alist-star.texinfo
+
@c <!-- FIXME: How much control over error messages is in SBCL?
@c _ How much should be? How much of this documentation should
@c _ we save or adapt?
@c _ which is useful when debugging macros.
@c _ \end{defvar}
@c _
-@c _ \begin{defvar}{}{error-print-length}
-@c _ \defvarx{error-print-level}
-@c _
-@c _ These variables are the print level and print length used in
-@c _ printing error messages. The default values are \code{5} and
-@c _ \code{3}. If null, the global values of \code{*print-level*} and
-@c _ \code{*print-length*} are used.
-@c _ \end{defvar}
-@c _
@c _ \begin{defmac}{extensions:}{define-source-context}{%
@c _ \args{\var{name} \var{lambda-list} \mstar{form}}}
@c _
@c _
@c _ -->
-
@node Diagnostic Severity
@comment node-name, next, previous, up
@subsection Diagnostic Severity
In the debugger, it is possible to override the printing behaviour of
the REPL.
-@defvr {Variable} sb-debug:*debug-print-variable-alist*
-
-An association list describing new bindings for special variables
-(typically *PRINT-FOO* variables) to be used within the debugger, e.g.
-@lisp
-((*PRINT-LENGTH* . 10) (*PRINT-LEVEL* . 6) (*PRINT-PRETTY* . NIL))
-@end lisp
-The variables in the @code{car} position are bound to the values in
-the @code{cdr} during the execution of some debug commands. When
-evaluating arbitrary expressions in the debugger, the normal values of
-the printer control variables are in effect. @c FIXME: is this correct?
-@code{*debug-print-variable-alist*} does not contain any bindings
-initially.
-
-@end defvr
+@include var-sb-ext-star-debug-print-variable-alist-star.texinfo
@node Stack Frames
@comment node-name, next, previous, up
@end deffn
@deffn {Debugger Command} backtrace [@var{n}]
-Displays all the frames from the current to the bottom. Only shows
-@var{n} frames if specified. The printing is controlled by @code{*debug-print-variable-alist*}.
+Displays all the frames from the current to the bottom. Only shows
+@var{n} frames if specified. The printing is controlled by
+@code{*debug-print-variable-alist*}.
@end deffn
@deffn {Debugger Command} step
is still mixed indiscriminately with low-level internal implementation stuff
like *STACK-TOP-HINT* and unsupported stuff like *TRACED-FUN-LIST*."
:use ("CL" "SB!EXT" "SB!INT" "SB!SYS" "SB!KERNEL")
+ :reexport ("*DEBUG-PRINT-VARIABLE-ALIST*")
:export ("*DEBUG-BEGINNER-HELP-P*"
"*DEBUG-CONDITION*"
- "*DEBUG-PRINT-LENGTH*" "*DEBUG-PRINT-LEVEL*"
- "*DEBUG-PRINT-VARIABLE-ALIST*"
"*DEBUG-READTABLE*" "*DEBUG-HELP-STRING*"
"*FLUSH-DEBUG-ERRORS*" "*IN-THE-DEBUGGER*"
"*TRACE-INDENTATION-STEP*" "*MAX-TRACE-INDENTATION*"
"*GC-RUN-TIME*"
"PURIFY"
+ ;; Customizing printing of compiler and debugger messages
+ "*COMPILER-PRINT-VARIABLE-ALIST*"
+ "*DEBUG-PRINT-VARIABLE-ALIST*"
+
;; Hooks into init & save sequences
"*INIT-HOOKS*" "*SAVE-HOOKS*"
"BINDING*"
"!DEF-BOOLEAN-ATTRIBUTE"
"WITH-REBOUND-IO-SYNTAX"
+ "WITH-SANE-IO-SYNTAX"
;; ..and CONDITIONs..
"BUG"
;;; to satisfy lambda list
;;; #:
;;; exactly 2 expected, but 5 found
-;;;
-;;; FIXME: These variables were deprecated in late February 2004, and
-;;; can probably be removed in about a year.
-(defvar *debug-print-level* 5
+(defvar *debug-print-variable-alist* nil
#!+sb-doc
- "(This is deprecated in favor of *DEBUG-PRINT-VARIABLE-ALIST*.)
+ "an association list describing new bindings for special variables
+to be used within the debugger. Eg.
-*PRINT-LEVEL* for the debugger")
-(defvar *debug-print-length* 7
- #!+sb-doc
- "(This is deprecated in favor of *DEBUG-PRINT-VARIABLE-ALIST*.)
+ ((*PRINT-LENGTH* . 10) (*PRINT-LEVEL* . 6) (*PRINT-PRETTY* . NIL))
-*PRINT-LENGTH* for the debugger")
+The variables in the CAR positions are bound to the values in the CDR
+during the execution of some debug commands. When evaluating arbitrary
+expressions in the debugger, the normal values of the printer control
+variables are in effect.
-(defvar *debug-print-variable-alist* nil
- #!+sb-doc
- "an association list describing new bindings for special variables
-(typically *PRINT-FOO* variables) to be used within the debugger, e.g.
-((*PRINT-LENGTH* . 10) (*PRINT-LEVEL* . 6) (*PRINT-PRETTY* . NIL))")
+Initially empty, *DEBUG-PRINT-VARIABLE-ALIST* is typically used to
+provide bindings for printer control variables.")
(defvar *debug-readtable*
;; KLUDGE: This can't be initialized in a cold toplevel form,
Any command -- including the name of a restart -- may be uniquely abbreviated.
The debugger rebinds various special variables for controlling i/o, sometimes
to defaults (much like WITH-STANDARD-IO-SYNTAX does) and sometimes to
- its own special values, e.g. SB-DEBUG:*DEBUG-PRINT-LEVEL*.
+ its own special values, based on SB-EXT:*DEBUG-PRINT-VARIBALE-ALIST*.
Debug commands do not affect *, //, and similar variables, but evaluation in
the debug loop does affect these variables.
SB-DEBUG:*FLUSH-DEBUG-ERRORS* controls whether errors at the debug prompt
(original-package *package*)
(original-print-pretty *print-pretty*))
(with-standard-io-syntax
- (let (;; We want the printer and reader to be in a useful state,
- ;; regardless of where the debugger was invoked in the
- ;; program. WITH-STANDARD-IO-SYNTAX did much of what we
- ;; want, but
- ;; * It doesn't affect our internal special variables
- ;; like *CURRENT-LEVEL-IN-PRINT*.
- ;; * It isn't customizable.
- ;; * It doesn't set *PRINT-READABLY* to the same value
- ;; as the toplevel default.
- ;; * It sets *PACKAGE* to COMMON-LISP-USER, which is not
- ;; helpful behavior for a debugger.
- ;; * There's no particularly good debugger default for
- ;; *PRINT-PRETTY*, since T is usually what you want
- ;; -- except absolutely not what you want when you're
- ;; debugging failures in PRINT-OBJECT logic.
- ;; We try to address all these issues with explicit
- ;; rebindings here.
- (sb!kernel:*current-level-in-print* 0)
- (*package* original-package)
- (*print-pretty* original-print-pretty)
- (*print-readably* nil)
- ;; Clear the circularity machinery to try to to reduce the
- ;; pain from sharing the circularity table across all
- ;; streams; if these are not rebound here, then setting
- ;; *PRINT-CIRCLE* within the debugger when debugging in a
- ;; state where something circular was being printed (e.g.,
- ;; because the debugger was entered on an error in a
- ;; PRINT-OBJECT method) makes a hopeless mess. Binding them
- ;; here does seem somewhat ugly because it makes it more
- ;; difficult to debug the printing-of-circularities code
- ;; itself; however, as far as I (WHN, 2004-05-29) can see,
- ;; that's almost entirely academic as long as there's one
- ;; shared *C-H-T* for all streams (i.e., it's already
- ;; unreasonably difficult to debug print-circle machinery
- ;; given the buggy crosstalk between the debugger streams
- ;; and the stream you're trying to watch), and any fix for
- ;; that buggy arrangement will likely let this hack go away
- ;; naturally.
- (sb!impl::*circularity-hash-table* . nil)
- (sb!impl::*circularity-counter* . nil)
- ;; These rebindings are now (as of early 2004) deprecated,
- ;; with the new *PRINT-VAR-ALIST* mechanism preferred.
- (*print-length* *debug-print-length*)
- (*print-level* *debug-print-level*)
- (*readtable* *debug-readtable*))
- (progv
- ;; (Why NREVERSE? PROGV makes the later entries have
- ;; precedence over the earlier entries.
- ;; *DEBUG-PRINT-VARIABLE-ALIST* is called an alist, so it's
- ;; expected that its earlier entries have precedence. And
- ;; the earlier-has-precedence behavior is mostly more
- ;; convenient, so that programmers can use PUSH or LIST* to
- ;; customize *DEBUG-PRINT-VARIABLE-ALIST*.)
- (nreverse (mapcar #'car *debug-print-variable-alist*))
- (nreverse (mapcar #'cdr *debug-print-variable-alist*))
- (apply fun rest))))))
+ (with-sane-io-syntax
+ (let (;; We want the printer and reader to be in a useful
+ ;; state, regardless of where the debugger was invoked
+ ;; in the program. WITH-STANDARD-IO-SYNTAX and
+ ;; WITH-SANE-IO-SYNTAX do much of what we want, but
+ ;; * It doesn't affect our internal special variables
+ ;; like *CURRENT-LEVEL-IN-PRINT*.
+ ;; * It isn't customizable.
+ ;; * It sets *PACKAGE* to COMMON-LISP-USER, which is not
+ ;; helpful behavior for a debugger.
+ ;; * There's no particularly good debugger default for
+ ;; *PRINT-PRETTY*, since T is usually what you want
+ ;; -- except absolutely not what you want when you're
+ ;; debugging failures in PRINT-OBJECT logic.
+ ;; We try to address all these issues with explicit
+ ;; rebindings here.
+ (sb!kernel:*current-level-in-print* 0)
+ (*package* original-package)
+ (*print-pretty* original-print-pretty)
+ ;; Clear the circularity machinery to try to to reduce the
+ ;; pain from sharing the circularity table across all
+ ;; streams; if these are not rebound here, then setting
+ ;; *PRINT-CIRCLE* within the debugger when debugging in a
+ ;; state where something circular was being printed (e.g.,
+ ;; because the debugger was entered on an error in a
+ ;; PRINT-OBJECT method) makes a hopeless mess. Binding them
+ ;; here does seem somewhat ugly because it makes it more
+ ;; difficult to debug the printing-of-circularities code
+ ;; itself; however, as far as I (WHN, 2004-05-29) can see,
+ ;; that's almost entirely academic as long as there's one
+ ;; shared *C-H-T* for all streams (i.e., it's already
+ ;; unreasonably difficult to debug print-circle machinery
+ ;; given the buggy crosstalk between the debugger streams
+ ;; and the stream you're trying to watch), and any fix for
+ ;; that buggy arrangement will likely let this hack go away
+ ;; naturally.
+ (sb!impl::*circularity-hash-table* . nil)
+ (sb!impl::*circularity-counter* . nil)
+ (*readtable* *debug-readtable*))
+ (progv
+ ;; (Why NREVERSE? PROGV makes the later entries have
+ ;; precedence over the earlier entries.
+ ;; *DEBUG-PRINT-VARIABLE-ALIST* is called an alist, so it's
+ ;; expected that its earlier entries have precedence. And
+ ;; the earlier-has-precedence behavior is mostly more
+ ;; convenient, so that programmers can use PUSH or LIST* to
+ ;; customize *DEBUG-PRINT-VARIABLE-ALIST*.)
+ (nreverse (mapcar #'car *debug-print-variable-alist*))
+ (nreverse (mapcar #'cdr *debug-print-variable-alist*))
+ (apply fun rest)))))))
;;; the ordinary ANSI case of INVOKE-DEBUGGER, when not suppressed by
;;; command-line --disable-debugger option
(*read-suppress* *read-suppress*)
(*readtable* *readtable*))
(funcall function)))
+
+;;; Bind a few "potentially dangerous" printer control variables to
+;;; safe values, respecting current values if possible.
+(defmacro with-sane-io-syntax (&body forms)
+ `(call-with-sane-io-syntax (lambda () ,@forms)))
+
+(defun call-with-sane-io-syntax (function)
+ (declare (type function function))
+ (macrolet ((true (sym)
+ `(and (boundp ',sym) ,sym)))
+ (let ((*print-readably* nil)
+ (*print-level* (or (true *print-level*) 6))
+ (*print-length* (or (true *print-length*) 12)))
+ (funcall function))))
(defun style-warn (format-control &rest format-arguments)
(/show0 "entering STYLE-WARN")
(/show format-control format-arguments)
- (warn 'simple-style-warning
- :format-control format-control
- :format-arguments format-arguments))
+ (with-sane-io-syntax
+ (warn 'simple-style-warning
+ :format-control format-control
+ :format-arguments format-arguments)))
;;; a utility for SIGNAL, ERROR, CERROR, WARN, COMPILER-NOTIFY and
;;; INVOKE-DEBUGGER: Parse the hairy argument conventions into a
(declaim (special *current-path*))
-;;; We bind print level and length when printing out messages so that
-;;; we don't dump huge amounts of garbage.
-;;;
-;;; FIXME: It's not possible to get the defaults right for everyone.
-;;; So: Should these variables be in the SB-EXT package? Or should we
-;;; just get rid of them completely and just use the bare
-;;; CL:*PRINT-FOO* variables instead?
-(declaim (type (or unsigned-byte null)
- *compiler-error-print-level*
- *compiler-error-print-length*
- *compiler-error-print-lines*))
-(defvar *compiler-error-print-level* 5
- #!+sb-doc
- "the value for *PRINT-LEVEL* when printing compiler error messages")
-(defvar *compiler-error-print-length* 10
- #!+sb-doc
- "the value for *PRINT-LENGTH* when printing compiler error messages")
-(defvar *compiler-error-print-lines* 12
- #!+sb-doc
- "the value for *PRINT-LINES* when printing compiler error messages")
-
(defvar *enclosing-source-cutoff* 1
#!+sb-doc
"The maximum number of enclosing non-original source forms (i.e. from
;;; compiler warnings.
(defun stringify-form (form &optional (pretty t))
(with-standard-io-syntax
- (let ((*print-readably* nil)
- (*print-pretty* pretty)
- (*print-level* *compiler-error-print-level*)
- (*print-length* *compiler-error-print-length*)
- (*print-lines* *compiler-error-print-lines*))
- (if pretty
- (format nil "~<~@; ~S~:>" (list form))
- (prin1-to-string form)))))
+ (with-compiler-io-syntax
+ (let ((*print-pretty* pretty))
+ (if pretty
+ (format nil "~<~@; ~S~:>" (list form))
+ (prin1-to-string form))))))
;;; Return a COMPILER-ERROR-CONTEXT structure describing the current
;;; error context, or NIL if we can't figure anything out. ARGS is a
;;;
;;; We suppress printing of messages identical to the previous, but
;;; record the number of times that the message is repeated.
-(defun print-compiler-message (format-string format-args)
+(defmacro print-compiler-message (format-string format-args)
+ `(with-compiler-io-syntax
+ (%print-compiler-message ,format-string ,format-args)))
+(defun %print-compiler-message (format-string format-args)
(declare (type simple-string format-string))
- (declare (type list format-args))
-
+ (declare (type list format-args))
(let ((stream *error-output*)
(context (find-error-context format-args)))
(cond
(note-message-repeats nil)
(setq *last-format-string* format-string)
(setq *last-format-args* format-args)
- (let ((*print-level* *compiler-error-print-level*)
- (*print-length* *compiler-error-print-length*)
- (*print-lines* *compiler-error-print-lines*))
- (format stream "~&")
- (pprint-logical-block (stream nil :per-line-prefix "; ")
- (format stream "~&~?" format-string format-args))
- (format stream "~&"))))
-
+ (format stream "~&")
+ (pprint-logical-block (stream nil :per-line-prefix "; ")
+ (format stream "~&~?" format-string format-args))
+ (format stream "~&")))
+
(incf *last-message-count*)
(values))
(defmacro position-or-lose (&rest args)
`(or (position ,@args)
(error "shouldn't happen?")))
+
+;;; user-definable compiler io syntax
+
+;;; We use WITH-SANE-IO-SYNTAX to provide safe defaults, and provide
+;;; *COMPILER-PRINT-VARIABLE-ALIST* for user customization.
+(defvar *compiler-print-variable-alist* nil
+ #!+sb-doc
+ "an association list describing new bindings for special variables
+to be used by the compiler for error-reporting, etc. Eg.
+
+ ((*PRINT-LENGTH* . 10) (*PRINT-LEVEL* . 6) (*PRINT-PRETTY* . NIL))
+
+The variables in the CAR positions are bound to the values in the CDR
+during the execution of some debug commands. When evaluating arbitrary
+expressions in the debugger, the normal values of the printer control
+variables are in effect.
+
+Initially empty, *COMPILER-PRINT-VARIABLE-ALIST* is Typically used to
+specify bindings for printer control variables.")
+
+(defmacro with-compiler-io-syntax (&body forms)
+ `(with-sane-io-syntax
+ (progv
+ (nreverse (mapcar #'car *compiler-print-variable-alist*))
+ (nreverse (mapcar #'cdr *compiler-print-variable-alist*))
+ ,@forms)))
(warning (c)
(error "shouldn't warn just from macroexpansion here"))))
+;;; bug 318 symptom no 1. (rest not fixed yet)
+(catch :ok
+ (handler-bind ((error (lambda (c)
+ ;; Used to cause stack-exhaustion
+ (unless (typep c 'storege-condition)
+ (throw :ok)))))
+ (eval '(progn
+ (defstruct foo a)
+ (setf (find-class 'foo) nil)
+ (defstruct foo slot-1)))))
+
;;; success
(format t "~&/returning success~%")
(quit :unix-status 104)
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.16.10"
+"0.8.16.11"