ruby-changes:48714
From: normal <ko1@a...>
Date: Sat, 18 Nov 2017 11:01:49 +0900 (JST)
Subject: [ruby-changes:48714] normal:r60830 (trunk): dir: release GVL on opendir
normal 2017-11-18 11:01:44 +0900 (Sat, 18 Nov 2017) New Revision: 60830 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60830 Log: 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 Modified files: trunk/dir.c Index: dir.c =================================================================== --- dir.c (revision 60829) +++ dir.c (revision 60830) @@ -490,6 +490,24 @@ dir_s_alloc(VALUE klass) https://github.com/ruby/ruby/blob/trunk/dir.c#L490 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, VA https://github.com/ruby/ruby/blob/trunk/dir.c#L554 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 https://github.com/ruby/ruby/blob/trunk/dir.c#L1429 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 https://github.com/ruby/ruby/blob/trunk/dir.c#L1440 dirp = fdopendir(fd); } #else - dirp = opendir(path); + dirp = opendir_without_gvl(path); #endif if (dirp) break; e = errno; -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/