X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Ftoplevel.lisp;h=f4baf40f061c756b75d8f4f5f8698dc885c8f383;hb=4ecf0abf29f8a8cb2a59c67e192e1f83efaa31f7;hp=7389eb5f34033c183e34a2b7725ae170f0eb7acc;hpb=ec2616d216958a608581802c47496c0194478dc8;p=sbcl.git diff --git a/src/code/toplevel.lisp b/src/code/toplevel.lisp index 7389eb5..f4baf40 100644 --- a/src/code/toplevel.lisp +++ b/src/code/toplevel.lisp @@ -65,7 +65,8 @@ (/show0 "back from INFINITE-ERROR-PROTECTOR") (let ((*current-error-depth* (1+ *current-error-depth*))) (/show0 "in INFINITE-ERROR-PROTECT, incremented error depth") - #+sb-show (sb-debug:backtrace) + ;; arbitrary truncation + #!+sb-show (sb!debug:backtrace 8) ,@forms))) ;;; a helper function for INFINITE-ERROR-PROTECT @@ -152,75 +153,89 @@ ;;; Zero the unused portion of the control stack so that old objects ;;; are not kept alive because of uninitialized stack variables. -;;; -;;; FIXME: Why do we need to do this instead of just letting GC read -;;; the stack pointer and avoid messing with the unused portion of -;;; the control stack? (Is this a multithreading thing where there's -;;; one control stack and stack pointer per thread, and it might not -;;; be easy to tell what a thread's stack pointer value is when -;;; looking in from another thread?) + +;;; "To summarize the problem, since not all allocated stack frame +;;; slots are guaranteed to be written by the time you call an another +;;; function or GC, there may be garbage pointers retained in your +;;; dead stack locations. The stack scrubbing only affects the part +;;; of the stack from the SP to the end of the allocated stack." +;;; - ram, on cmucl-imp, Tue, 25 Sep 2001 + +;;; So, as an (admittedly lame) workaround, from time to time we call +;;; scrub-control-stack to zero out all the unused portion. This is +;;; supposed to happen when the stack is mostly empty, so that we have +;;; a chance of clearing more of it: callers are currently (2002.07.18) +;;; REPL and SUB-GC + (defun scrub-control-stack () (declare (optimize (speed 3) (safety 0)) (values (unsigned-byte 20))) ; FIXME: DECLARE VALUES? - #!+stack-grows-upward - (labels - ((scrub (ptr offset count) - (declare (type system-area-pointer ptr) - (type (unsigned-byte 16) offset) - (type (unsigned-byte 20) count) - (values (unsigned-byte 20))) - (cond ((= offset bytes-per-scrub-unit) - (look (sap+ ptr bytes-per-scrub-unit) 0 count)) - (t - (setf (sap-ref-32 ptr offset) 0) - (scrub ptr (+ offset sb!vm:n-word-bytes) count)))) - (look (ptr offset count) - (declare (type system-area-pointer ptr) - (type (unsigned-byte 16) offset) - (type (unsigned-byte 20) count) - (values (unsigned-byte 20))) - (cond ((= offset bytes-per-scrub-unit) - count) - ((zerop (sap-ref-32 ptr offset)) - (look ptr (+ offset sb!vm:n-word-bytes) count)) - (t - (scrub ptr offset (+ count sb!vm:n-word-bytes)))))) - (let* ((csp (sap-int (sb!c::control-stack-pointer-sap))) - (initial-offset (logand csp (1- bytes-per-scrub-unit)))) + #!-stack-grows-downward-not-upward + (let* ((csp (sap-int (sb!c::control-stack-pointer-sap))) + (initial-offset (logand csp (1- bytes-per-scrub-unit))) + (end-of-stack + (- sb!vm:control-stack-end sb!c:*backend-page-size*))) + (labels + ((scrub (ptr offset count) + (declare (type system-area-pointer ptr) + (type (unsigned-byte 16) offset) + (type (unsigned-byte 20) count) + (values (unsigned-byte 20))) + (cond ((>= (sap-int ptr) end-of-stack) 0) + ((= offset bytes-per-scrub-unit) + (look (sap+ ptr bytes-per-scrub-unit) 0 count)) + (t + (setf (sap-ref-32 ptr offset) 0) + (scrub ptr (+ offset sb!vm:n-word-bytes) count)))) + (look (ptr offset count) + (declare (type system-area-pointer ptr) + (type (unsigned-byte 16) offset) + (type (unsigned-byte 20) count) + (values (unsigned-byte 20))) + (cond ((>= (sap-int ptr) end-of-stack) 0) + ((= offset bytes-per-scrub-unit) + count) + ((zerop (sap-ref-32 ptr offset)) + (look ptr (+ offset sb!vm:n-word-bytes) count)) + (t + (scrub ptr offset (+ count sb!vm:n-word-bytes)))))) (declare (type (unsigned-byte 32) csp)) (scrub (int-sap (- csp initial-offset)) (* (floor initial-offset sb!vm:n-word-bytes) sb!vm:n-word-bytes) 0))) - #!+stack-grows-downward - (labels - ((scrub (ptr offset count) - (declare (type system-area-pointer ptr) - (type (unsigned-byte 16) offset) - (type (unsigned-byte 20) count) - (values (unsigned-byte 20))) - (let ((loc (int-sap (- (sap-int ptr) (+ offset sb!vm:n-word-bytes))))) - (cond ((= offset bytes-per-scrub-unit) - (look (int-sap (- (sap-int ptr) bytes-per-scrub-unit)) - 0 count)) - (t ;; need to fix bug in %SET-STACK-REF - (setf (sap-ref-32 loc 0) 0) - (scrub ptr (+ offset sb!vm:n-word-bytes) count))))) - (look (ptr offset count) - (declare (type system-area-pointer ptr) - (type (unsigned-byte 16) offset) - (type (unsigned-byte 20) count) - (values (unsigned-byte 20))) - (let ((loc (int-sap (- (sap-int ptr) offset)))) - (cond ((= offset bytes-per-scrub-unit) - count) - ((zerop (sb!kernel::get-lisp-obj-address (stack-ref loc 0))) - (look ptr (+ offset sb!vm:n-word-bytes) count)) - (t - (scrub ptr offset (+ count sb!vm:n-word-bytes))))))) - (let* ((csp (sap-int (sb!c::control-stack-pointer-sap))) - (initial-offset (logand csp (1- bytes-per-scrub-unit)))) + #!+stack-grows-downward-not-upward + (let* ((csp (sap-int (sb!c::control-stack-pointer-sap))) + (end-of-stack (+ sb!vm:control-stack-start sb!c:*backend-page-size*)) + (initial-offset (logand csp (1- bytes-per-scrub-unit)))) + (labels + ((scrub (ptr offset count) + (declare (type system-area-pointer ptr) + (type (unsigned-byte 16) offset) + (type (unsigned-byte 20) count) + (values (unsigned-byte 20))) + (let ((loc (int-sap (- (sap-int ptr) (+ offset sb!vm:n-word-bytes))))) + (cond ((< (sap-int loc) end-of-stack) 0) + ((= offset bytes-per-scrub-unit) + (look (int-sap (- (sap-int ptr) bytes-per-scrub-unit)) + 0 count)) + (t ;; need to fix bug in %SET-STACK-REF + (setf (sap-ref-32 loc 0) 0) + (scrub ptr (+ offset sb!vm:n-word-bytes) count))))) + (look (ptr offset count) + (declare (type system-area-pointer ptr) + (type (unsigned-byte 16) offset) + (type (unsigned-byte 20) count) + (values (unsigned-byte 20))) + (let ((loc (int-sap (- (sap-int ptr) offset)))) + (cond ((< (sap-int loc) end-of-stack) 0) + ((= offset bytes-per-scrub-unit) + count) + ((zerop (sb!kernel::get-lisp-obj-address (stack-ref loc 0))) + (look ptr (+ offset sb!vm:n-word-bytes) count)) + (t + (scrub ptr offset (+ count sb!vm:n-word-bytes))))))) (declare (type (unsigned-byte 32) csp)) (scrub (int-sap (+ csp initial-offset)) (* (floor initial-offset sb!vm:n-word-bytes) sb!vm:n-word-bytes) @@ -245,7 +260,10 @@ "Evaluate FORM, returning whatever it returns and adjusting ***, **, *, +++, ++, +, ///, //, /, and -." (setf - form) - (let ((results (multiple-value-list (eval form)))) + (let ((results + (multiple-value-list + (eval-in-lexenv form + (make-null-interactive-lexenv))))) (setf /// // // / / results @@ -285,7 +303,6 @@ (reversed-evals nil) ; values of --eval options, in reverse order; and ; also --load options, translated into --eval (noprint nil) ; Has a --noprint option been seen? - (noprogrammer nil) ; Has a --noprogrammer option been seen? (options (rest *posix-argv*))) ; skipping program name (/show0 "done with outer LET in TOPLEVEL-INIT") @@ -338,9 +355,16 @@ ((string= option "--noprint") (pop-option) (setf noprint t)) + ;; FIXME: --noprogrammer was deprecated in 0.7.5, and + ;; in a year or so this backwards compatibility can + ;; go away. ((string= option "--noprogrammer") + (warn "treating deprecated --noprogrammer as --disable-debugger") + (pop-option) + (push '(disable-debugger) reversed-evals)) + ((string= option "--disable-debugger") (pop-option) - (setf noprogrammer t)) + (push '(disable-debugger) reversed-evals)) ((string= option "--end-toplevel-options") (pop-option) (return)) @@ -365,14 +389,6 @@ ;; user-level options are left visible to user code. (setf (rest *posix-argv*) options) - ;; Handle --noprogrammer option. We intentionally do this - ;; early so that it will affect the handling of initialization - ;; files and --eval options. - (/show0 "handling --noprogrammer option in TOPLEVEL-INIT") - (when noprogrammer - (setf *debugger-hook* 'noprogrammer-debugger-hook-fun - *debug-io* *error-output*)) - ;; Handle initialization files. (/show0 "handling initialization files in TOPLEVEL-INIT") (flet (;; If any of POSSIBLE-INIT-FILE-NAMES names a real file, @@ -449,6 +465,15 @@ ;; (classic CMU CL error message: "You're certainly a clever child.":-) (critically-unreachable "after TOPLEVEL-REPL")))) +;;; halt-on-failures and prompt-on-failures modes, suitable for +;;; noninteractive and interactive use respectively +(defun disable-debugger () + (setf *debugger-hook* 'noprogrammer-debugger-hook-fun + *debug-io* *error-output*)) +(defun enable-debugger () + (setf *debugger-hook* nil + *debug-io* *query-io*)) + ;;; read-eval-print loop for the default system toplevel (defun toplevel-repl (noprint) (/show0 "entering TOPLEVEL-REPL") @@ -475,9 +500,13 @@ ;; get you out to here. (with-simple-restart (abort - "Reduce debugger level (leaving debugger, returning to toplevel).") + "~@") (catch 'toplevel-catcher - (sb!unix:unix-sigsetmask 0) ; FIXME: What is this for? + #!-sunos (sb!unix:unix-sigsetmask 0) ; FIXME: What is this for? + ;; in the event of a control-stack-exhausted-error, we should + ;; have unwound enough stack by the time we get here that this + ;; is now possible + (sb!kernel::protect-control-stack-guard-page 1) (repl noprint) (critically-unreachable "after REPL"))))))) @@ -485,10 +514,7 @@ (/show0 "entering REPL") (let ((eof-marker (cons :eof nil))) (loop - ;; FIXME: It seems bad to have GC behavior depend on scrubbing the - ;; control stack before each interactive command. Isn't there some - ;; way we can convince the GC to just ignore dead areas of the - ;; control stack, so that we don't need to rely on this half-measure? + ;; see comment preceding definition of SCRUB-CONTROL-STACK (scrub-control-stack) (unless noprint (fresh-line) @@ -505,10 +531,11 @@ (fresh-line) (prin1 result)))))))))) +;;; suitable value for *DEBUGGER-HOOK* for a noninteractive Unix-y program (defun noprogrammer-debugger-hook-fun (condition old-debugger-hook) (declare (ignore old-debugger-hook)) (flet ((failure-quit (&key recklessly-p) - (/show0 "in FAILURE-QUIT (in noprogrammer debugger hook)") + (/show0 "in FAILURE-QUIT (in --disable-debugger debugger hook)") (quit :unix-status 1 :recklessly-p recklessly-p))) ;; This HANDLER-CASE is here mostly to stop output immediately ;; (and fall through to QUIT) when there's an I/O error. Thus, @@ -530,8 +557,9 @@ ;; (Where to truncate the BACKTRACE is of course arbitrary, but ;; it seems as though we should at least truncate it somewhere.) (sb!debug:backtrace 128 *error-output*) - (format *error-output* - "~%unhandled condition in --noprogrammer mode, quitting~%") + (format + *error-output* + "~%unhandled condition in --disable-debugger mode, quitting~%") (finish-output *error-output*) (failure-quit)) (condition () @@ -552,7 +580,8 @@ ;; what that is responsible, but that it's possible at all ;; means that we should IGNORE-ERRORS here. -- WHN 2001-04-24 (ignore-errors - (%primitive print "Argh! error within --noprogrammer error handling")) + (%primitive print + "Argh! error within --disable-debugger error handling")) (failure-quit :recklessly-p t))))) ;;; a convenient way to get into the assembly-level debugger