diff options
-rw-r--r-- | error.c | 8 | ||||
-rw-r--r-- | internal.h | 3 | ||||
-rw-r--r-- | load.c | 4 | ||||
-rw-r--r-- | test/ruby/test_exception.rb | 34 | ||||
-rw-r--r-- | vm_backtrace.c | 16 |
5 files changed, 53 insertions, 12 deletions
@@ -145,10 +145,16 @@ rb_warning_s_warn(VALUE mod, VALUE str) return Qnil; } +VALUE +rb_warning_warn(VALUE mod, VALUE str) +{ + return rb_funcallv(mod, id_warn, 1, &str); +} + static void rb_write_warning_str(VALUE str) { - rb_funcall(rb_mWarning, id_warn, 1, str); + rb_warning_warn(rb_mWarning, str); } static VALUE diff --git a/internal.h b/internal.h index afea318376..0988f301dd 100644 --- a/internal.h +++ b/internal.h @@ -1139,6 +1139,7 @@ VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method); NORETURN(void ruby_deprecated_internal_feature(const char *)); #define DEPRECATED_INTERNAL_FEATURE(func) \ (ruby_deprecated_internal_feature(func), UNREACHABLE) +VALUE rb_warning_warn(VALUE mod, VALUE str); /* eval.c */ VALUE rb_refinement_module_get_refined_class(VALUE module); @@ -1749,7 +1750,7 @@ 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); +void rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output); RUBY_SYMBOL_EXPORT_BEGIN const char *rb_objspace_data_type_name(VALUE obj); @@ -719,6 +719,8 @@ rb_f_load(int argc, VALUE *argv) return Qtrue; } +extern VALUE rb_mWarning; + static char * load_lock(const char *ftptr) { @@ -742,7 +744,7 @@ load_lock(const char *ftptr) } if (RTEST(ruby_verbose)) { rb_warning("loading in progress, circular require considered harmful - %s", ftptr); - rb_backtrace_print_to(rb_stderr); + rb_backtrace_each(rb_warning_warn, rb_mWarning); } switch (rb_thread_shield_wait((VALUE)data)) { case Qfalse: diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index 1179c26c51..8a8edd2ff2 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -943,23 +943,23 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end end - def test_warning_warn + def capture_warning_warn verbose = $VERBOSE - warning = nil + warning = [] ::Warning.class_eval do alias_method :warn2, :warn remove_method :warn define_method(:warn) do |str| - warning = str + warning << str end end $VERBOSE = true - a = @a + yield - assert_match(/instance variable @a not initialized/, warning) + return warning ensure $VERBOSE = verbose @@ -970,6 +970,11 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end end + def test_warning_warn + warning = capture_warning_warn {@a} + assert_match(/instance variable @a not initialized/, warning[0]) + end + def test_warning_warn_invalid_argument assert_raise(TypeError) do ::Warning.warn nil @@ -982,6 +987,25 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end end + def test_warning_warn_circular_require_backtrace + warning = nil + path = nil + Tempfile.create(%w[circular .rb]) do |t| + path = t.path + basename = File.basename(path) + t.puts "require '#{basename}'" + t.close + $LOAD_PATH.push(File.dirname(t)) + warning = capture_warning_warn {require basename} + ensure + $LOAD_PATH.pop + $LOADED_FEATURES.delete(t) + end + assert_match(/circular require/, warning.first) + warning.pop while %r[lib/rubygems/core_ext/kernel_require.rb:] =~ warning.last + assert_operator(warning.last, :start_with?, "\tfrom #{path}:1:") + end + def test_undefined_backtrace assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") begin; diff --git a/vm_backtrace.c b/vm_backtrace.c index 6a5dadf709..a5ab52e349 100644 --- a/vm_backtrace.c +++ b/vm_backtrace.c @@ -772,10 +772,15 @@ rb_backtrace(void) vm_backtrace_print(stderr); } +struct print_to_arg { + VALUE (*iter)(VALUE recv, VALUE str); + VALUE output; +}; + static void oldbt_print_to(void *data, VALUE file, int lineno, VALUE name) { - VALUE output = (VALUE)data; + const struct print_to_arg *arg = data; VALUE str = rb_sprintf("\tfrom %"PRIsVALUE":%d:in ", file, lineno); if (NIL_P(name)) { @@ -784,16 +789,19 @@ oldbt_print_to(void *data, VALUE file, int lineno, VALUE name) else { rb_str_catf(str, " `%"PRIsVALUE"'\n", name); } - rb_io_write(output, str); + (*arg->iter)(arg->output, str); } void -rb_backtrace_print_to(VALUE output) +rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output) { struct oldbt_arg arg; + struct print_to_arg parg; + parg.iter = iter; + parg.output = output; arg.func = oldbt_print_to; - arg.data = (void *)output; + arg.data = &parg; backtrace_each(GET_THREAD(), oldbt_init, oldbt_iter_iseq, |