mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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 `<main>'
This commit is contained in:
+7
-2
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user