From ee61a0d8cefb5ccfba266a1e0407415adb88b150 Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Wed, 24 Jul 2002 22:10:31 +0000 Subject: [PATCH] 0.7.6.something More stack checking fixes ... when frobbing signal context on x86, set arg count (ecx) to 0, should fix problem observed on OpenBSD ... define a special control-stack-exhausted condition so that ignore-errors won't ignore stack exhaustion ... fix the test to match the condition --- NEWS | 7 +++++++ src/code/error.lisp | 7 +++++++ src/code/interr.lisp | 3 ++- src/runtime/interrupt.c | 4 +++- tests/exhaust.impure.lisp | 20 +++++++++++++------- version.lisp-expr | 2 +- 6 files changed, 33 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 007ccd9..b6464e0 100644 --- a/NEWS +++ b/NEWS @@ -1199,6 +1199,13 @@ changes in sbcl-0.7.7 relative to sbcl-0.7.6: * More fixes have been made to treatment of floating point exception treatment and other Unix signals. In particular, floating point exceptions no longer cause Bus errors on the SPARC/Linux platform. + * The detection and handling of control stack exhaustion (infinite + or very deeply nested recursion) has changed. Stack exhaustion + detection is now done by write-protecting pages at the OS level + and applies at all optimization settings; when found, a + SB-KERNEL:CONTROL-STACK_EXHAUSTED condition (subclass of + STORAGE-CONDITION) is signalled, so stack exhaustion can no longer + be caught using IGNORE-ERRORS planned incompatible changes in 0.7.x: * When the profiling interface settles down, maybe in 0.7.x, maybe diff --git a/src/code/error.lisp b/src/code/error.lisp index 1239eb4..25ef8e3 100644 --- a/src/code/error.lisp +++ b/src/code/error.lisp @@ -55,3 +55,10 @@ (define-condition parse-unknown-type (condition) ((specifier :reader parse-unknown-type-specifier :initarg :specifier))) +(define-condition control-stack-exhausted (storage-condition) + () + (:report + (lambda (condition stream) + (format stream + "Control stack exhausted (no more space for function call frames). This is probably due to heavily nested or infinitely recursive function calls, or a tail call that SBCL cannot or has not optimized away.")))) + diff --git a/src/code/interr.lisp b/src/code/interr.lisp index 02147a8..2ff5f81 100644 --- a/src/code/interr.lisp +++ b/src/code/interr.lisp @@ -488,6 +488,7 @@ (infinite-error-protect (format *error-output* "Control stack guard page temporarily disabled: proceed with caution~%") - (error "Control stack exhausted (no more space for function call frames). This is probably due to heavily nested or infinitely recursive function calls, or a tail call that SBCL cannot or has not optimized away.")))) + (error 'control-stack-exhausted)))) + diff --git a/src/runtime/interrupt.c b/src/runtime/interrupt.c index da023bf..c5e70aa 100644 --- a/src/runtime/interrupt.c +++ b/src/runtime/interrupt.c @@ -539,9 +539,11 @@ boolean handle_control_stack_guard_triggered(os_context_t *context,void *addr) build_fake_control_stack_frames(context); /* signal handler will "return" to this error-causing function */ *os_context_pc_addr(context) = function; -#ifndef LISP_FEATURE_X86 +#ifdef LISP_FEATURE_X86 /* this much of the calling convention is common to all non-x86 ports */ + *os_context_register_addr(context,reg_ECX) = 0; +#else *os_context_register_addr(context,reg_NARGS) = 0; *os_context_register_addr(context,reg_LIP) = function; *os_context_register_addr(context,reg_CFP) = diff --git a/tests/exhaust.impure.lisp b/tests/exhaust.impure.lisp index 0956f29..fc432b4 100644 --- a/tests/exhaust.impure.lisp +++ b/tests/exhaust.impure.lisp @@ -14,13 +14,19 @@ (cl:in-package :cl-user) ;;; Prior to sbcl-0.7.1.38, doing something like (RECURSE), even in -;;; safe code, would crash the entire Lisp process. Now it should -;;; signal an error in a context where the soft stack limit has been -;;; relaxed enough that the error can be handled. +;;; safe code, would crash the entire Lisp process. Then the soft +;;; stack checking was introduced, which checked (in safe code) for +;;; stack exhaustion at each lambda. + +;;; Post 0.7.6.1, this was rewritten to use mprotect()-based stack +;;; protection which does not require lisp code to check anything, +;;; and works at all optimization settings. However, it now signals a +;;; STORAGE-CONDITION instead of an ERROR, so this test needs revising (locally - (declare (optimize safety)) (defun recurse () (recurse) (recurse)) - (ignore-errors (recurse))) + (handler-case + (recurse) + (storage-condition (c) (declare (ignore c)) (quit :unix-status 104)))) -;;; success -(quit :unix-status 104) +;;; oops +(quit :unix-status 1) diff --git a/version.lisp-expr b/version.lisp-expr index fe432d1..136a7be 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -18,4 +18,4 @@ ;;; for internal versions, especially for internal versions off the ;;; main CVS branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.7.6.4" +"0.7.6.5" -- 1.7.10.4