diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-09 03:46:39 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-09 03:46:39 +0000 |
commit | dceb897e5ab55468767c308af7680108cb0e482c (patch) | |
tree | 76c89a5f3886e28f68a85af7f239c1d46230380d /dir.c | |
parent | 933fabd1b9a48591dc589527c5f99b64598dd2e9 (diff) | |
download | ruby-dceb897e5ab55468767c308af7680108cb0e482c.tar.gz |
Dir#chdir keeps GVL if passed block
On further examination, Dir.chdir with a block from multiple
threads is thread-unsafe given our use of the chdir_blocking and
chdir_thread global variables.
This bug was only introduced in r60583 so not part of any stable
release.
Dir.chdir without a block can still make senses in a MT context
as only one thread could be cwd-sensitive and other threads do
not care which directory they're in.
* dir.c (dir_chdir): keep GVL here
(dir_s_chdir): release GVL if no block given
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61091 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 14 |
1 files changed, 8 insertions, 6 deletions
@@ -1002,11 +1002,7 @@ nogvl_chdir(void *ptr) static void dir_chdir(VALUE path) { - int r; - char *p = RSTRING_PTR(path); - - r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_chdir, p, RUBY_UBF_IO, 0); - if (r < 0) + if (chdir(RSTRING_PTR(path)) < 0) rb_sys_fail_path(path); } @@ -1111,7 +1107,13 @@ dir_s_chdir(int argc, VALUE *argv, VALUE obj) args.done = FALSE; return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args); } - dir_chdir(path); + else { + char *p = RSTRING_PTR(path); + int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_chdir, p, + RUBY_UBF_IO, 0); + if (r < 0) + rb_sys_fail_path(path); + } return INT2FIX(0); } |