mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44170 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4547d773c2
commit
0aed7c6874
6 changed files with 89 additions and 1 deletions
16
ChangeLog
16
ChangeLog
|
@ -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>
|
Fri Dec 13 12:01:07 2013 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* gc.c (garbage_collect_body): use rb_bug() and explicit error message
|
* gc.c (garbage_collect_body): use rb_bug() and explicit error message
|
||||||
|
|
25
error.c
25
error.c
|
@ -736,6 +736,30 @@ exc_backtrace(VALUE exc)
|
||||||
return obj;
|
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
|
VALUE
|
||||||
rb_check_backtrace(VALUE bt)
|
rb_check_backtrace(VALUE bt)
|
||||||
{
|
{
|
||||||
|
@ -1749,6 +1773,7 @@ Init_Exception(void)
|
||||||
rb_define_method(rb_eException, "message", exc_message, 0);
|
rb_define_method(rb_eException, "message", exc_message, 0);
|
||||||
rb_define_method(rb_eException, "inspect", exc_inspect, 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", 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, "set_backtrace", exc_set_backtrace, 1);
|
||||||
rb_define_method(rb_eException, "cause", exc_cause, 0);
|
rb_define_method(rb_eException, "cause", exc_cause, 0);
|
||||||
|
|
||||||
|
|
2
eval.c
2
eval.c
|
@ -493,10 +493,12 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
|
||||||
if (OBJ_FROZEN(mesg)) {
|
if (OBJ_FROZEN(mesg)) {
|
||||||
mesg = rb_obj_dup(mesg);
|
mesg = rb_obj_dup(mesg);
|
||||||
}
|
}
|
||||||
|
rb_iv_set(mesg, "bt_locations", at);
|
||||||
set_backtrace(mesg, at);
|
set_backtrace(mesg, at);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NIL_P(mesg)) {
|
if (!NIL_P(mesg)) {
|
||||||
th->errinfo = mesg;
|
th->errinfo = mesg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -800,6 +800,7 @@ VALUE rb_make_backtrace(void);
|
||||||
void rb_backtrace_print_as_bugreport(void);
|
void rb_backtrace_print_as_bugreport(void);
|
||||||
int rb_backtrace_p(VALUE obj);
|
int rb_backtrace_p(VALUE obj);
|
||||||
VALUE rb_backtrace_to_str_ary(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);
|
void rb_backtrace_print_to(VALUE output);
|
||||||
VALUE rb_vm_backtrace_object(void);
|
VALUE rb_vm_backtrace_object(void);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,36 @@ class TestBacktrace < Test::Unit::TestCase
|
||||||
assert_match(/.+:\d+:.+/, bt[0])
|
assert_match(/.+:\d+:.+/, bt[0])
|
||||||
end
|
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
|
def test_caller_lev
|
||||||
cs = []
|
cs = []
|
||||||
Fiber.new{
|
Fiber.new{
|
||||||
|
|
|
@ -372,6 +372,7 @@ typedef struct rb_backtrace_struct {
|
||||||
rb_backtrace_location_t *backtrace_base;
|
rb_backtrace_location_t *backtrace_base;
|
||||||
int backtrace_size;
|
int backtrace_size;
|
||||||
VALUE strary;
|
VALUE strary;
|
||||||
|
VALUE locary;
|
||||||
} rb_backtrace_t;
|
} rb_backtrace_t;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -383,8 +384,9 @@ backtrace_mark(void *ptr)
|
||||||
|
|
||||||
for (i=0; i<s; i++) {
|
for (i=0; i<s; i++) {
|
||||||
location_mark_entry(&bt->backtrace[i]);
|
location_mark_entry(&bt->backtrace[i]);
|
||||||
rb_gc_mark(bt->strary);
|
|
||||||
}
|
}
|
||||||
|
rb_gc_mark(bt->strary);
|
||||||
|
rb_gc_mark(bt->locary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,6 +633,18 @@ backtrace_to_location_ary(VALUE self, long lev, long n)
|
||||||
return r;
|
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
|
static VALUE
|
||||||
backtrace_dump_data(VALUE self)
|
backtrace_dump_data(VALUE self)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue