Skip to content

Commit

Permalink
* error.c: add Exception#backtrace_locations.
Browse files Browse the repository at this point in the history
  Now, there are no setter and independent from Exception#backtrace.
  [Feature ruby#8960]
* eval.c (setup_exception): set backtrace locations for `bt_location'
  special attribute.
* vm_backtrace.c (rb_backtrace_to_location_ary): added.
* internal.h: ditto.
* test/ruby/test_backtrace.rb: add a test for
  Exception#backtrace_locations.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44170 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information
ko1 committed Dec 13, 2013
1 parent 4547d77 commit 0aed7c6
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 1 deletion.
16 changes: 16 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
Fri Dec 13 13:25:30 2013 Koichi Sasada <ko1@atdot.net>

* error.c: add Exception#backtrace_locations.
Now, there are no setter and independent from Exception#backtrace.
[Feature #8960]

* eval.c (setup_exception): set backtrace locations for `bt_location'
special attribute.

* vm_backtrace.c (rb_backtrace_to_location_ary): added.

* internal.h: ditto.

* test/ruby/test_backtrace.rb: add a test for
Exception#backtrace_locations.

Fri Dec 13 12:01:07 2013 Koichi Sasada <ko1@atdot.net>

* gc.c (garbage_collect_body): use rb_bug() and explicit error message
Expand Down
25 changes: 25 additions & 0 deletions error.c
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,30 @@ exc_backtrace(VALUE exc)
return obj;
}

/*
* call-seq:
* exception.backtrace_locations -> array
*
* Returns any backtrace associated with the exception. This method is
* similar to Exception#backtrace, but the backtrace is an array of
* Thread::Backtrace::Location.
*
* Now, this method is not affected by Exception#set_backtrace().
*/
static VALUE
exc_backtrace_locations(VALUE exc)
{
ID bt_locations;
VALUE obj;

CONST_ID(bt_locations, "bt_locations");
obj = rb_attr_get(exc, bt_locations);
if (!NIL_P(obj)) {
obj = rb_backtrace_to_location_ary(obj);
}
return obj;
}

VALUE
rb_check_backtrace(VALUE bt)
{
Expand Down Expand Up @@ -1749,6 +1773,7 @@ Init_Exception(void)
rb_define_method(rb_eException, "message", exc_message, 0);
rb_define_method(rb_eException, "inspect", exc_inspect, 0);
rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
rb_define_method(rb_eException, "backtrace_locations", exc_backtrace_locations, 0);
rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
rb_define_method(rb_eException, "cause", exc_cause, 0);

Expand Down
2 changes: 2 additions & 0 deletions eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,10 +493,12 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
if (OBJ_FROZEN(mesg)) {
mesg = rb_obj_dup(mesg);
}
rb_iv_set(mesg, "bt_locations", at);
set_backtrace(mesg, at);
}
}
}

if (!NIL_P(mesg)) {
th->errinfo = mesg;
}
Expand Down
1 change: 1 addition & 0 deletions internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,7 @@ VALUE rb_make_backtrace(void);
void rb_backtrace_print_as_bugreport(void);
int rb_backtrace_p(VALUE obj);
VALUE rb_backtrace_to_str_ary(VALUE obj);
VALUE rb_backtrace_to_location_ary(VALUE obj);
void rb_backtrace_print_to(VALUE output);
VALUE rb_vm_backtrace_object(void);

Expand Down
30 changes: 30 additions & 0 deletions test/ruby/test_backtrace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,36 @@ def test_exception
assert_match(/.+:\d+:.+/, bt[0])
end

def helper_test_exception_backtrace_locations
raise
end

def test_exception_backtrace_locations
bt = Fiber.new{
begin
raise
rescue => e
e.backtrace_locations
end
}.resume
assert_equal(1, bt.size)
assert_match(/.+:\d+:.+/, bt[0].to_s)

bt = Fiber.new{
begin
begin
helper_test_exception_backtrace_locations
rescue
raise
end
rescue => e
e.backtrace_locations
end
}.resume
assert_equal(2, bt.size)
assert_match(/helper_test_exception_backtrace_locations/, bt[0].to_s)
end

def test_caller_lev
cs = []
Fiber.new{
Expand Down
16 changes: 15 additions & 1 deletion vm_backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ typedef struct rb_backtrace_struct {
rb_backtrace_location_t *backtrace_base;
int backtrace_size;
VALUE strary;
VALUE locary;
} rb_backtrace_t;

static void
Expand All @@ -383,8 +384,9 @@ backtrace_mark(void *ptr)

for (i=0; i<s; i++) {
location_mark_entry(&bt->backtrace[i]);
rb_gc_mark(bt->strary);
}
rb_gc_mark(bt->strary);
rb_gc_mark(bt->locary);
}
}

Expand Down Expand Up @@ -631,6 +633,18 @@ backtrace_to_location_ary(VALUE self, long lev, long n)
return r;
}

VALUE
rb_backtrace_to_location_ary(VALUE self)
{
rb_backtrace_t *bt;
GetCoreDataFromValue(self, rb_backtrace_t, bt);

if (!bt->locary) {
bt->locary = backtrace_to_location_ary(self, 0, 0);
}
return bt->locary;
}

static VALUE
backtrace_dump_data(VALUE self)
{
Expand Down

0 comments on commit 0aed7c6

Please sign in to comment.