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:
nobu 2013-10-08 15:56:01 +00:00
Родитель 42976d75f3
Коммит 21e858e518
5 изменённых файлов: 49 добавлений и 9 удалений

Просмотреть файл

@ -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>
* 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);
int rb_backtrace_p(VALUE obj);
VALUE rb_backtrace_to_str_ary(VALUE obj);
void rb_backtrace_print_to(VALUE output);
VALUE rb_vm_backtrace_object();
RUBY_SYMBOL_EXPORT_BEGIN

3
load.c
Просмотреть файл

@ -706,8 +706,7 @@ load_lock(const char *ftptr)
}
if (RTEST(ruby_verbose)) {
rb_warning("loading in progress, circular require considered harmful - %s", ftptr);
/* TODO: display to $stderr, not stderr in C */
rb_backtrace();
rb_backtrace_print_to(rb_stderr);
}
switch (rb_thread_shield_wait((VALUE)data)) {
case Qfalse:

Просмотреть файл

@ -399,6 +399,7 @@ class TestRequire < Test::Unit::TestCase
def test_race_exception
bug5754 = '[ruby-core:41618]'
path = nil
stderr = $stderr
Tempfile.create(%w"bug5754 .rb") {|tmp|
path = tmp.path
tmp.print %{\
@ -416,12 +417,11 @@ class TestRequire < Test::Unit::TestCase
}
tmp.close
# "circular require" warnings to $stderr, but backtraces to stderr
# in C-level. And redirecting stderr to a pipe seems to change
# some blocking timings and causes a deadlock, so run in a
# separated process for the time being.
assert_separately(["-w", "-", path, bug5754], <<-'end;', ignore_stderr: true)
path, bug5754 = *ARGV
class << (output = "")
alias write concat
end
$stderr = output
start = false
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([:pre, :post], scratch, bug5754)
end;
assert_match(/circular require/, output)
assert_match(/in #{__method__}'$/o, output)
}
ensure
$stderr = stderr
$".delete(path)
end

Просмотреть файл

@ -768,6 +768,35 @@ rb_backtrace(void)
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
rb_make_backtrace(void)
{