diff options
-rw-r--r-- | dir.c | 13 | ||||
-rw-r--r-- | test/ruby/test_dir.rb | 25 |
2 files changed, 27 insertions, 11 deletions
@@ -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) |