зеркало из https://github.com/github/ruby.git
Backtrace for SystemStackError
* eval.c (setup_exception): set backtrace in system stack error other than the pre-allocated sysstack_error. [Feature #6216] * proc.c (Init_Proc): freeze the pre-allocated sysstack_error. * vm_insnhelper.c (vm_stackoverflow): raise new instance for each times without calling any methods to keep the backtrace with no further stack overflow. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46502 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
cf3890205f
Коммит
053759edfc
11
ChangeLog
11
ChangeLog
|
@ -1,4 +1,13 @@
|
|||
Mon Jun 23 11:32:59 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
Mon Jun 23 11:35:01 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* eval.c (setup_exception): set backtrace in system stack error
|
||||
other than the pre-allocated sysstack_error. [Feature #6216]
|
||||
|
||||
* proc.c (Init_Proc): freeze the pre-allocated sysstack_error.
|
||||
|
||||
* vm_insnhelper.c (vm_stackoverflow): raise new instance for each
|
||||
times without calling any methods to keep the backtrace with no
|
||||
further stack overflow.
|
||||
|
||||
* object.c (rb_obj_copy_ivar): extract function to copy instance
|
||||
variables only for T_OBJECT from init_copy.
|
||||
|
|
11
eval.c
11
eval.c
|
@ -460,6 +460,12 @@ exc_setup_cause(VALUE exc, VALUE cause)
|
|||
return exc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
sysstack_error_p(VALUE exc)
|
||||
{
|
||||
return exc == sysstack_error || (!SPECIAL_CONST_P(exc) && RBASIC_CLASS(exc) == rb_eSysStackError);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause)
|
||||
{
|
||||
|
@ -497,8 +503,7 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause)
|
|||
rb_iv_set(mesg, "bt", at);
|
||||
}
|
||||
else {
|
||||
at = get_backtrace(mesg);
|
||||
if (NIL_P(at)) {
|
||||
if (sysstack_error_p(mesg) || NIL_P(at = get_backtrace(mesg))) {
|
||||
at = rb_vm_backtrace_object();
|
||||
if (OBJ_FROZEN(mesg)) {
|
||||
mesg = rb_obj_dup(mesg);
|
||||
|
@ -697,7 +702,7 @@ make_exception(int argc, const VALUE *argv, int isstr)
|
|||
exc = argv[0];
|
||||
n = 1;
|
||||
exception_call:
|
||||
if (exc == sysstack_error) return exc;
|
||||
if (sysstack_error_p(exc)) return exc;
|
||||
CONST_ID(exception, "exception");
|
||||
mesg = rb_check_funcall(exc, exception, n, argv+1);
|
||||
if (mesg == Qundef) {
|
||||
|
|
1
proc.c
1
proc.c
|
@ -2748,6 +2748,7 @@ Init_Proc(void)
|
|||
sysstack_error = rb_exc_new3(rb_eSysStackError,
|
||||
rb_obj_freeze(rb_str_new2("stack level too deep")));
|
||||
OBJ_TAINT(sysstack_error);
|
||||
OBJ_FREEZE(sysstack_error);
|
||||
|
||||
/* utility functions */
|
||||
rb_define_global_function("proc", rb_block_proc, 0);
|
||||
|
|
|
@ -529,7 +529,8 @@ end.join
|
|||
end
|
||||
|
||||
def test_stackoverflow
|
||||
assert_raise(SystemStackError){m}
|
||||
e = assert_raise(SystemStackError){m}
|
||||
assert_operator(e.backtrace.size, :>, 10)
|
||||
end
|
||||
|
||||
def test_machine_stackoverflow
|
||||
|
|
|
@ -27,7 +27,9 @@ static rb_control_frame_t *vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_cont
|
|||
static void
|
||||
vm_stackoverflow(void)
|
||||
{
|
||||
rb_exc_raise(sysstack_error);
|
||||
VALUE e = rb_obj_alloc(rb_eSysStackError);
|
||||
rb_obj_copy_ivar(e, sysstack_error);
|
||||
rb_exc_raise(e);
|
||||
}
|
||||
|
||||
static inline rb_control_frame_t *
|
||||
|
|
Загрузка…
Ссылка в новой задаче