aboutsummaryrefslogtreecommitdiffstats
path: root/file.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-11-19 05:03:17 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-11-19 05:03:17 +0000
commit48a03987ca00d158dd30364ed7c1f9c537aaa9d2 (patch)
tree3b4a4be25aef0a0dadcd628012c1e985fa050a5c /file.c
parentbd4712d60f84f95dd9bddd0fed0cf5140ff3386f (diff)
downloadruby-48a03987ca00d158dd30364ed7c1f9c537aaa9d2.tar.gz
File.readlink and rb_readlink releases GVL
The `readlink' can stall on slow filesystems like `open' and `read' syscalls. Release the GVL and let the rest of the VM function while `readlink' runs. * file.c (nogvl_readlink): new function (readlink_without_gvl): ditto (rb_readlink): use readlink_without_gvl git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60845 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'file.c')
-rw-r--r--file.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/file.c b/file.c
index 1e4d5459c0..96f59f2bc7 100644
--- a/file.c
+++ b/file.c
@@ -2873,6 +2873,33 @@ rb_file_s_readlink(VALUE klass, VALUE path)
}
#ifndef _WIN32
+struct readlink_arg {
+ const char *path;
+ char *buf;
+ size_t size;
+};
+
+static void *
+nogvl_readlink(void *ptr)
+{
+ struct readlink_arg *ra = ptr;
+
+ return (void *)(VALUE)readlink(ra->path, ra->buf, ra->size);
+}
+
+static ssize_t
+readlink_without_gvl(VALUE path, VALUE buf, size_t size)
+{
+ struct readlink_arg ra;
+
+ ra.path = RSTRING_PTR(path);
+ ra.buf = RSTRING_PTR(buf);
+ ra.size = size;
+
+ return (ssize_t)rb_thread_call_without_gvl(nogvl_readlink, &ra,
+ RUBY_UBF_IO, 0);
+}
+
VALUE
rb_readlink(VALUE path, rb_encoding *enc)
{
@@ -2883,7 +2910,7 @@ rb_readlink(VALUE path, rb_encoding *enc)
FilePathValue(path);
path = rb_str_encode_ospath(path);
v = rb_enc_str_new(0, size, enc);
- while ((rv = readlink(RSTRING_PTR(path), RSTRING_PTR(v), size)) == size
+ while ((rv = readlink_without_gvl(path, v, size)) == size
#ifdef _AIX
|| (rv < 0 && errno == ERANGE) /* quirky behavior of GPFS */
#endif