ruby-changes:48972
From: normal <ko1@a...>
Date: Sat, 9 Dec 2017 12:46:43 +0900 (JST)
Subject: [ruby-changes:48972] normal:r61091 (trunk): Dir#chdir keeps GVL if passed block
normal 2017-12-09 12:46:39 +0900 (Sat, 09 Dec 2017) New Revision: 61091 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61091 Log: 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 Modified files: trunk/dir.c Index: dir.c =================================================================== --- dir.c (revision 61090) +++ dir.c (revision 61091) @@ -1002,11 +1002,7 @@ nogvl_chdir(void *ptr) https://github.com/ruby/ruby/blob/trunk/dir.c#L1002 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 https://github.com/ruby/ruby/blob/trunk/dir.c#L1107 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); } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/