aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--error.c6
-rw-r--r--internal.h1
-rw-r--r--io.c17
-rw-r--r--load.c1
-rw-r--r--test/ruby/test_require.rb7
6 files changed, 37 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 5c1647113e..924cfd0826 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Tue Dec 25 13:38:12 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * error.c (compile_err_append, compile_warn_print, warn_print): use
+ rb_write_error_str() instead of writing to rb_stderr directly.
+
+ * io.c (rb_write_error_str): a stopgap measure not to unblock GVL.
+ warning from require seems to still have race condition errors.
+
Tue Dec 25 00:59:29 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* node.h (NODE_OP_CDECL), compile.c (iseq_compile_each),
diff --git a/error.c b/error.c
index 95b846edb6..da24505eb0 100644
--- a/error.c
+++ b/error.c
@@ -115,7 +115,7 @@ compile_err_append(VALUE mesg)
th->errinfo = err;
}
rb_str_cat2(mesg, "\n");
- rb_io_write(rb_stderr, mesg);
+ rb_write_error_str(mesg);
}
/* returned to the parser world */
@@ -165,7 +165,7 @@ compile_warn_print(const char *file, int line, const char *fmt, va_list args)
str = compile_snprintf(NULL, "warning: ", file, line, fmt, args);
rb_str_cat2(str, "\n");
- rb_io_write(rb_stderr, str);
+ rb_write_error_str(str);
}
void
@@ -209,7 +209,7 @@ warn_print(const char *fmt, va_list args)
rb_str_cat2(str, "warning: ");
rb_str_vcatf(str, fmt, args);
rb_str_cat2(str, "\n");
- rb_io_write(rb_stderr, str);
+ rb_write_error_str(str);
}
void
diff --git a/internal.h b/internal.h
index 2f05f48595..13c36f7a2c 100644
--- a/internal.h
+++ b/internal.h
@@ -138,6 +138,7 @@ const char *ruby_get_inplace_mode(void);
void ruby_set_inplace_mode(const char *);
ssize_t rb_io_bufread(VALUE io, void *buf, size_t size);
void rb_stdio_set_default_encoding(void);
+void rb_write_error_str(VALUE mesg);
/* iseq.c */
VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase);
diff --git a/io.c b/io.c
index 53539da7b5..b6d5f4a80c 100644
--- a/io.c
+++ b/io.c
@@ -6980,6 +6980,23 @@ rb_write_error(const char *mesg)
rb_write_error2(mesg, strlen(mesg));
}
+void
+rb_write_error_str(VALUE mesg)
+{
+ /* a stopgap measure for the time being */
+ if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
+ size_t len = (size_t)RSTRING_LEN(mesg);
+ if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
+ RB_GC_GUARD(mesg);
+ return;
+ }
+ }
+ else {
+ /* may unlock GVL, and */
+ rb_io_write(rb_stderr, mesg);
+ }
+}
+
static void
must_respond_to(ID mid, VALUE val, ID id)
{
diff --git a/load.c b/load.c
index c0508fccb2..70e3ee8646 100644
--- a/load.c
+++ b/load.c
@@ -663,6 +663,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();
}
switch (rb_thread_shield_wait((VALUE)data)) {
diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb
index 4279acdde1..410edbb276 100644
--- a/test/ruby/test_require.rb
+++ b/test/ruby/test_require.rb
@@ -384,6 +384,12 @@ 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;')
+ path, bug5754 = *ARGV
start = false
scratch = []
@@ -416,6 +422,7 @@ 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;
ensure
$".delete(path)
tmp.close(true) if tmp