summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--error.c16
-rw-r--r--internal.h4
-rw-r--r--load.c7
-rw-r--r--test/ruby/test_exception.rb36
-rw-r--r--version.h6
-rw-r--r--vm_backtrace.c16
6 files changed, 69 insertions, 16 deletions
diff --git a/error.c b/error.c
index b890be13a8..ee805d4cc1 100644
--- a/error.c
+++ b/error.c
@@ -162,10 +162,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
@@ -254,6 +260,14 @@ rb_warning(const char *fmt, ...)
}
}
+VALUE
+rb_warning_string(const char *fmt, ...)
+{
+ with_warning_string(mesg, 0, fmt) {
+ }
+ return mesg;
+}
+
#if 0
void
rb_enc_warning(rb_encoding *enc, const char *fmt, ...)
diff --git a/internal.h b/internal.h
index cb758b94ad..6012376353 100644
--- a/internal.h
+++ b/internal.h
@@ -1033,6 +1033,8 @@ VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method);
rb_name_err_raise_str(rb_fstring_cstr(mesg), (recv), (name))
NORETURN(void ruby_only_for_internal_use(const char *));
#define ONLY_FOR_INTERNAL_USE(func) ruby_only_for_internal_use(func)
+VALUE rb_warning_warn(VALUE mod, VALUE str);
+VALUE rb_warning_string(const char *fmt, ...);
/* eval.c */
VALUE rb_refinement_module_get_refined_class(VALUE module);
@@ -1641,7 +1643,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);
VALUE rb_vm_backtrace_object(void);
RUBY_SYMBOL_EXPORT_BEGIN
diff --git a/load.c b/load.c
index 88e31e26f8..7778d4f87c 100644
--- a/load.c
+++ b/load.c
@@ -720,6 +720,8 @@ rb_f_load(int argc, VALUE *argv)
return Qtrue;
}
+extern VALUE rb_mWarning;
+
static char *
load_lock(const char *ftptr)
{
@@ -742,8 +744,9 @@ load_lock(const char *ftptr)
return (char *)"";
}
if (RTEST(ruby_verbose)) {
- rb_warning("loading in progress, circular require considered harmful - %s", ftptr);
- rb_backtrace_print_to(rb_stderr);
+ VALUE warning = rb_warning_string("loading in progress, circular require considered harmful - %s", ftptr);
+ rb_backtrace_each(rb_str_append, warning);
+ rb_warning_warn(rb_mWarning, warning);
}
switch (rb_thread_shield_wait((VALUE)data)) {
case Qfalse:
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index a6b707bcca..d7038bb578 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -934,23 +934,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
@@ -961,6 +961,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
@@ -973,6 +978,27 @@ $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|
+ begin
+ 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
+ end
+ assert_equal(1, warning.size)
+ assert_match(/circular require/, warning.first)
+ assert_match(/^\tfrom #{Regexp.escape(path)}:1:/, warning.first)
+ end
+
def test_undefined_backtrace
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
begin;
diff --git a/version.h b/version.h
index 43cba41397..da2bdb28dd 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "2.4.4"
-#define RUBY_RELEASE_DATE "2018-02-16"
-#define RUBY_PATCHLEVEL 236
+#define RUBY_RELEASE_DATE "2018-02-17"
+#define RUBY_PATCHLEVEL 237
#define RUBY_RELEASE_YEAR 2018
#define RUBY_RELEASE_MONTH 2
-#define RUBY_RELEASE_DAY 16
+#define RUBY_RELEASE_DAY 17
#include "ruby/version.h"
diff --git a/vm_backtrace.c b/vm_backtrace.c
index 1df7bb8b7f..b32f1e74eb 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -778,10 +778,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)) {
@@ -790,16 +795,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,