From d77c72dac5b46dacc8332bca73a8398ae2cf9a78 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Sun, 6 Mar 2016 11:51:04 +0900 Subject: Revert "Merge pull request #3126 from jbreeden/backtrace_irep_null_check" This reverts commit bf7719fe8da1b704c2cb72dd629dc75135fd1ad5, reversing changes made to 4f4fa0ade0fd80a3a6fa64bebcb5f71b0d4a8648. We should get backtrace while irep is alive. --- src/backtrace.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/backtrace.c b/src/backtrace.c index 5bf6d3196..45a8cc2de 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -111,8 +111,6 @@ each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func mrb_callinfo *ci; mrb_irep *irep; mrb_code *pc; - - loc.lineno = -1; ci = &mrb->c->cibase[i]; @@ -130,11 +128,8 @@ each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func else { pc = pc0; } - - if (irep) { - loc.filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq)); - loc.lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq)); - } + loc.filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq)); + loc.lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq)); if (loc.lineno == -1) continue; -- cgit v1.2.3 From f1eb3aea114cbd1e2622cbe9618571f3e1eec115 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Sun, 6 Mar 2016 11:58:54 +0900 Subject: Fix segmentation fault by backtrace and GC GitHub: fix #3122 It reverts #3126. #3126 fixes the segmentation fault but generates broken backtrace. This change fixes the segmentation fault and generates correct backtrace. The strategy of this change is "generating backtrace while irep is alive". /tmp/test.rb: def gen e0 = nil begin 1.times { raise 'foobar' } rescue => e e0 = e end e0 end e = gen GC.start gen GC.start puts e.backtrace.join("\n") Run: % bin/mruby /tmp/test.rb /tmp/test.rb:5:in Object.gen /home/kou/work/ruby/mruby.kou/mrblib/numeric.rb:77:in Integral#times /tmp/test.rb:4:in Object.gen /tmp/test.rb:13 FYI: % ruby -v /tmp/test.rb ruby 2.3.0p0 (2015-12-25) [x86_64-linux-gnu] /tmp/test.rb:5:in `block in gen' /tmp/test.rb:4:in `times' /tmp/test.rb:4:in `gen' /tmp/test.rb:13:in `
' --- src/error.c | 9 +++++++-- src/gc.c | 5 +++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/error.c b/src/error.c index 14e4ab4d3..13032b136 100644 --- a/src/error.c +++ b/src/error.c @@ -255,17 +255,22 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc) { if (!mrb->gc.out_of_memory && mrb->backtrace.n > 0) { mrb_value target_exc = mrb_nil_value(); + int ai; + + ai = mrb_gc_arena_save(mrb); if ((mrb->exc && !have_backtrace(mrb, mrb->exc))) { target_exc = mrb_obj_value(mrb->exc); } - else if (!mrb_nil_p(exc) && mrb_obj_ptr(exc) == mrb->backtrace.exc) { - target_exc = exc; + else if (!mrb_nil_p(exc) && mrb->backtrace.exc) { + target_exc = mrb_obj_value(mrb->backtrace.exc); + mrb_gc_protect(mrb, target_exc); } if (!mrb_nil_p(target_exc)) { mrb_value backtrace; backtrace = mrb_restore_backtrace(mrb); set_backtrace(mrb, target_exc, backtrace); } + mrb_gc_arena_restore(mrb, ai); } mrb->backtrace.n = 0; diff --git a/src/gc.c b/src/gc.c index b23e4869e..e7948e4f5 100644 --- a/src/gc.c +++ b/src/gc.c @@ -695,8 +695,13 @@ obj_free(mrb_state *mrb, struct RBasic *obj) #endif case MRB_TT_OBJECT: + mrb_gc_free_iv(mrb, (struct RObject*)obj); + break; + case MRB_TT_EXCEPTION: mrb_gc_free_iv(mrb, (struct RObject*)obj); + if ((struct RObject*)obj == mrb->backtrace.exc) + mrb->backtrace.exc = 0; break; case MRB_TT_CLASS: -- cgit v1.2.3