load.c: display backtrace to $stderr
* load.c (load_lock): display backtrace to $stderr at circular require. * vm_backtrace.c (rb_backtrace_print_to): new function to print backtrace to the given output. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43204 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
42976d75f3
commit
21e858e518
@ -1,3 +1,11 @@
|
|||||||
|
Wed Oct 9 00:55:51 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* load.c (load_lock): display backtrace to $stderr at circular
|
||||||
|
require.
|
||||||
|
|
||||||
|
* vm_backtrace.c (rb_backtrace_print_to): new function to print
|
||||||
|
backtrace to the given output.
|
||||||
|
|
||||||
Tue Oct 8 21:03:35 2013 Koichi Sasada <ko1@atdot.net>
|
Tue Oct 8 21:03:35 2013 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* vm_backtrace.c, include/ruby/debug.h: add new APIs
|
* vm_backtrace.c, include/ruby/debug.h: add new APIs
|
||||||
|
@ -744,6 +744,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);
|
||||||
|
void rb_backtrace_print_to(VALUE output);
|
||||||
VALUE rb_vm_backtrace_object();
|
VALUE rb_vm_backtrace_object();
|
||||||
|
|
||||||
RUBY_SYMBOL_EXPORT_BEGIN
|
RUBY_SYMBOL_EXPORT_BEGIN
|
||||||
|
3
load.c
3
load.c
@ -706,8 +706,7 @@ load_lock(const char *ftptr)
|
|||||||
}
|
}
|
||||||
if (RTEST(ruby_verbose)) {
|
if (RTEST(ruby_verbose)) {
|
||||||
rb_warning("loading in progress, circular require considered harmful - %s", ftptr);
|
rb_warning("loading in progress, circular require considered harmful - %s", ftptr);
|
||||||
/* TODO: display to $stderr, not stderr in C */
|
rb_backtrace_print_to(rb_stderr);
|
||||||
rb_backtrace();
|
|
||||||
}
|
}
|
||||||
switch (rb_thread_shield_wait((VALUE)data)) {
|
switch (rb_thread_shield_wait((VALUE)data)) {
|
||||||
case Qfalse:
|
case Qfalse:
|
||||||
|
@ -399,6 +399,7 @@ class TestRequire < Test::Unit::TestCase
|
|||||||
def test_race_exception
|
def test_race_exception
|
||||||
bug5754 = '[ruby-core:41618]'
|
bug5754 = '[ruby-core:41618]'
|
||||||
path = nil
|
path = nil
|
||||||
|
stderr = $stderr
|
||||||
Tempfile.create(%w"bug5754 .rb") {|tmp|
|
Tempfile.create(%w"bug5754 .rb") {|tmp|
|
||||||
path = tmp.path
|
path = tmp.path
|
||||||
tmp.print %{\
|
tmp.print %{\
|
||||||
@ -416,12 +417,11 @@ class TestRequire < Test::Unit::TestCase
|
|||||||
}
|
}
|
||||||
tmp.close
|
tmp.close
|
||||||
|
|
||||||
# "circular require" warnings to $stderr, but backtraces to stderr
|
class << (output = "")
|
||||||
# in C-level. And redirecting stderr to a pipe seems to change
|
alias write concat
|
||||||
# some blocking timings and causes a deadlock, so run in a
|
end
|
||||||
# separated process for the time being.
|
$stderr = output
|
||||||
assert_separately(["-w", "-", path, bug5754], <<-'end;', ignore_stderr: true)
|
|
||||||
path, bug5754 = *ARGV
|
|
||||||
start = false
|
start = false
|
||||||
|
|
||||||
scratch = []
|
scratch = []
|
||||||
@ -454,9 +454,12 @@ class TestRequire < Test::Unit::TestCase
|
|||||||
|
|
||||||
assert_equal(true, (t1_res ^ t2_res), bug5754 + " t1:#{t1_res} t2:#{t2_res}")
|
assert_equal(true, (t1_res ^ t2_res), bug5754 + " t1:#{t1_res} t2:#{t2_res}")
|
||||||
assert_equal([:pre, :post], scratch, bug5754)
|
assert_equal([:pre, :post], scratch, bug5754)
|
||||||
end;
|
|
||||||
|
assert_match(/circular require/, output)
|
||||||
|
assert_match(/in #{__method__}'$/o, output)
|
||||||
}
|
}
|
||||||
ensure
|
ensure
|
||||||
|
$stderr = stderr
|
||||||
$".delete(path)
|
$".delete(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -768,6 +768,35 @@ rb_backtrace(void)
|
|||||||
vm_backtrace_print(stderr);
|
vm_backtrace_print(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
oldbt_print_to(void *data, VALUE file, int lineno, VALUE name)
|
||||||
|
{
|
||||||
|
VALUE output = (VALUE)data;
|
||||||
|
VALUE str = rb_sprintf("\tfrom %"PRIsVALUE":%d:in ", file, lineno);
|
||||||
|
|
||||||
|
if (NIL_P(name)) {
|
||||||
|
rb_str_cat2(str, "unknown method\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rb_str_catf(str, " `%"PRIsVALUE"'\n", name);
|
||||||
|
}
|
||||||
|
rb_io_write(output, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_backtrace_print_to(VALUE output)
|
||||||
|
{
|
||||||
|
struct oldbt_arg arg;
|
||||||
|
|
||||||
|
arg.func = oldbt_print_to;
|
||||||
|
arg.data = (void *)output;
|
||||||
|
backtrace_each(GET_THREAD(),
|
||||||
|
oldbt_init,
|
||||||
|
oldbt_iter_iseq,
|
||||||
|
oldbt_iter_cfunc,
|
||||||
|
&arg);
|
||||||
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_make_backtrace(void)
|
rb_make_backtrace(void)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user