aboutsummaryrefslogtreecommitdiffstats
path: root/dir.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-11-18 02:01:44 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-11-18 02:01:44 +0000
commit8b3836f39db7a0412900a6e770487c40d48876a9 (patch)
tree684efc4fc7611383dae187ef26cf429fb51f28b2 /dir.c
parent2af345fbc59f13a122c4348fb986a2b9619a6910 (diff)
downloadruby-8b3836f39db7a0412900a6e770487c40d48876a9.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
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/dir.c b/dir.c
index baeaa4db7e..e044228a5b 100644
--- a/dir.c
+++ b/dir.c
@@ -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;