diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-11-18 02:01:44 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-11-18 02:01:44 +0000 |
commit | 089eb0c5cedaa405efe024a4cf5e58faf2bc4a78 (patch) | |
tree | 684efc4fc7611383dae187ef26cf429fb51f28b2 | |
parent | 28d00c2fb2949c67f9510d61c41ad58047c4ab01 (diff) | |
download | ruby-089eb0c5cedaa405efe024a4cf5e58faf2bc4a78.tar.gz |
dir: release GVL on opendir
opendir(3) is subject to the same pathological slowdowns on
slow or unreliable filesystems as open(2), so release the GVL
to avoid stalling the entire VM like we do with IO#open
* dir.c (nogvl_opendir): new function
(opendir_without_gvl): new function
(dir_initialize): s/opendir/&_without_gvl/
(do_opendir): ditto
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60830 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | dir.c | 28 |
1 files changed, 23 insertions, 5 deletions
@@ -490,6 +490,24 @@ dir_s_alloc(VALUE klass) return obj; } +static void * +nogvl_opendir(void *ptr) +{ + const char *path = ptr; + + return (void *)opendir(path); +} + +static DIR * +opendir_without_gvl(const char *path) +{ + union { const char *in; void *out; } u; + + u.in = path; + + return rb_thread_call_without_gvl(nogvl_opendir, u.out, RUBY_UBF_IO, 0); +} + /* * call-seq: * Dir.new( string ) -> aDir @@ -536,18 +554,18 @@ dir_initialize(int argc, VALUE *argv, VALUE dir) RB_OBJ_WRITE(dir, &dp->path, Qnil); dp->enc = fsenc; path = RSTRING_PTR(dirname); - dp->dir = opendir(path); + dp->dir = opendir_without_gvl(path); if (dp->dir == NULL) { int e = errno; if (rb_gc_for_fd(e)) { - dp->dir = opendir(path); + dp->dir = opendir_without_gvl(path); } #ifdef HAVE_GETATTRLIST else if (e == EIO) { u_int32_t attrbuf[1]; struct attrlist al = {ATTR_BIT_MAP_COUNT, 0}; if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) { - dp->dir = opendir(path); + dp->dir = opendir_without_gvl(path); } } #endif @@ -1411,7 +1429,7 @@ do_opendir(const int basefd, const char *path, int flags, rb_encoding *enc, fd = openat(basefd, path, 0, opendir_flags); dirp = (fd < 0) ? NULL : fdopendir(fd); #else - dirp = opendir(path); + dirp = opendir_without_gvl(path); #endif if (!dirp) { int e = errno; @@ -1422,7 +1440,7 @@ do_opendir(const int basefd, const char *path, int flags, rb_encoding *enc, dirp = fdopendir(fd); } #else - dirp = opendir(path); + dirp = opendir_without_gvl(path); #endif if (dirp) break; e = errno; |