summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--internal.h1
-rw-r--r--load.c3
-rw-r--r--test/ruby/test_require.rb17
-rw-r--r--vm_backtrace.c29
5 files changed, 49 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index d6af7c8..e0055c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/internal.h b/internal.h
index c96245d..7d9a8aa 100644
--- a/internal.h
+++ b/internal.h
@@ -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
diff --git a/load.c b/load.c
index 03ce062..c5dd4e7 100644
--- a/load.c
+++ b/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:
diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb
index 34c5fde..ad08bf8 100644
--- a/test/ruby/test_require.rb
+++ b/test/ruby/test_require.rb
@@ -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
diff --git a/vm_backtrace.c b/vm_backtrace.c
index 8155c85..1f2e8c3 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -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)
{