summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dir.c13
-rw-r--r--test/ruby/test_dir.rb25
2 files changed, 27 insertions, 11 deletions
diff --git a/dir.c b/dir.c
index 92262d34ed..00113850d7 100644
--- a/dir.c
+++ b/dir.c
@@ -1043,14 +1043,20 @@ dir_chdir0(VALUE path)
static struct {
VALUE thread;
+ VALUE path;
+ int line;
int blocking;
} chdir_lock = {
.blocking = 0, .thread = Qnil,
+ .path = Qnil, .line = 0,
};
static void
chdir_enter(void)
{
+ if (chdir_lock.blocking == 0) {
+ chdir_lock.path = rb_source_location(&chdir_lock.line);
+ }
chdir_lock.blocking++;
if (NIL_P(chdir_lock.thread)) {
chdir_lock.thread = rb_thread_current();
@@ -1063,6 +1069,8 @@ chdir_leave(void)
chdir_lock.blocking--;
if (chdir_lock.blocking == 0) {
chdir_lock.thread = Qnil;
+ chdir_lock.path = Qnil;
+ chdir_lock.line = 0;
}
}
@@ -1075,6 +1083,9 @@ chdir_alone_block_p(void)
rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block");
if (!block_given) {
rb_warn("conflicting chdir during another chdir block");
+ if (!NIL_P(chdir_lock.path)) {
+ rb_compile_warn(RSTRING_PTR(chdir_lock.path), chdir_lock.line, "here");
+ }
}
}
return block_given;
@@ -3640,6 +3651,8 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname)
void
Init_Dir(void)
{
+ rb_gc_register_address(&chdir_lock.path);
+
rb_cDir = rb_define_class("Dir", rb_cObject);
rb_include_module(rb_cDir, rb_mEnumerable);
diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb
index 026338f567..7468d3fc76 100644
--- a/test/ruby/test_dir.rb
+++ b/test/ruby/test_dir.rb
@@ -104,22 +104,23 @@ class TestDir < Test::Unit::TestCase
assert_raise(ArgumentError) { Dir.chdir }
ENV["HOME"] = pwd
Dir.chdir do
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+ conflicting = /conflicting chdir during another chdir block\n^#{Regexp.quote(__FILE__)}:#{__LINE__-1}:/
+ assert_warning(conflicting) { Dir.chdir(pwd) }
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) }
+ assert_warning(conflicting) { Dir.chdir(@root) }
assert_equal(@root, Dir.pwd)
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+ assert_warning(conflicting) { Dir.chdir(pwd) }
assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) }.join }
assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) { } }.join }
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+ assert_warning(conflicting) { Dir.chdir(pwd) }
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) }
+ assert_warning(conflicting) { Dir.chdir(@root) }
assert_equal(@root, Dir.pwd)
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+ assert_warning(conflicting) { Dir.chdir(pwd) }
Dir.chdir(@root) do
assert_equal(@root, Dir.pwd)
end
@@ -142,23 +143,25 @@ class TestDir < Test::Unit::TestCase
ENV["HOME"] = pwd
ret = root_dir.chdir do |*a|
+ conflicting = /conflicting chdir during another chdir block\n^#{Regexp.quote(__FILE__)}:#{__LINE__-1}:/
+
assert_empty(a)
- assert_warning(/conflicting chdir during another chdir block/) { dir.chdir }
- assert_warning(/conflicting chdir during another chdir block/) { root_dir.chdir }
+ assert_warning(conflicting) { dir.chdir }
+ assert_warning(conflicting) { root_dir.chdir }
assert_equal(@root, Dir.pwd)
assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; dir.chdir }.join }
assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; dir.chdir{} }.join }
- assert_warning(/conflicting chdir during another chdir block/) { dir.chdir }
+ assert_warning(conflicting) { dir.chdir }
assert_equal(pwd, Dir.pwd)
- assert_warning(/conflicting chdir during another chdir block/) { root_dir.chdir }
+ assert_warning(conflicting) { root_dir.chdir }
assert_equal(@root, Dir.pwd)
- assert_warning(/conflicting chdir during another chdir block/) { dir.chdir }
+ assert_warning(conflicting) { dir.chdir }
root_dir.chdir do
assert_equal(@root, Dir.pwd)