summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-09 03:46:39 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-09 03:46:39 +0000
commitdceb897e5ab55468767c308af7680108cb0e482c (patch)
tree76c89a5f3886e28f68a85af7f239c1d46230380d /dir.c
parent933fabd1b9a48591dc589527c5f99b64598dd2e9 (diff)
downloadruby-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.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/dir.c b/dir.c
index 378396a9f7..be20c43ce1 100644
--- a/dir.c
+++ b/dir.c
@@ -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);
}