ruby-changes:34421
From: nobu <ko1@a...>
Date: Mon, 23 Jun 2014 11:35:24 +0900 (JST)
Subject: [ruby-changes:34421] nobu:r46502 (trunk): Backtrace for SystemStackError
nobu 2014-06-23 11:35:18 +0900 (Mon, 23 Jun 2014) New Revision: 46502 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=46502 Log: 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. Modified files: trunk/ChangeLog trunk/eval.c trunk/proc.c trunk/test/ruby/test_exception.rb trunk/vm_insnhelper.c Index: ChangeLog =================================================================== --- ChangeLog (revision 46501) +++ ChangeLog (revision 46502) @@ -1,4 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 -Mon Jun 23 11:32:59 2014 Nobuyoshi Nakada <nobu@r...> +Mon Jun 23 11:35:01 2014 Nobuyoshi Nakada <nobu@r...> + + * 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. Index: proc.c =================================================================== --- proc.c (revision 46501) +++ proc.c (revision 46502) @@ -2748,6 +2748,7 @@ Init_Proc(void) https://github.com/ruby/ruby/blob/trunk/proc.c#L2748 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); Index: eval.c =================================================================== --- eval.c (revision 46501) +++ eval.c (revision 46502) @@ -460,6 +460,12 @@ exc_setup_cause(VALUE exc, VALUE cause) https://github.com/ruby/ruby/blob/trunk/eval.c#L460 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 https://github.com/ruby/ruby/blob/trunk/eval.c#L503 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 *ar https://github.com/ruby/ruby/blob/trunk/eval.c#L702 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) { Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 46501) +++ vm_insnhelper.c (revision 46502) @@ -27,7 +27,9 @@ static rb_control_frame_t *vm_get_ruby_l https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L27 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 * Index: test/ruby/test_exception.rb =================================================================== --- test/ruby/test_exception.rb (revision 46501) +++ test/ruby/test_exception.rb (revision 46502) @@ -529,7 +529,8 @@ end.join https://github.com/ruby/ruby/blob/trunk/test/ruby/test_exception.rb#L529 end def test_stackoverflow - assert_raise(SystemStackError){m} + e = assert_raise(SystemStackError){m} + assert_operator(e.backtrace.size, :>, 10) end def test_machine_stackoverflow -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/