From 17dd212f001572f157a0b1b4b4fc706778b02102 Mon Sep 17 00:00:00 2001 From: normal Date: Tue, 28 Nov 2017 03:28:35 +0000 Subject: [PATCH] file: release GVL for access(2) syscalls Like stat(2), the access(2) syscall may take an indeterminate amount of time on slow/remote filesystems. This lets the following methods release the GVL to avoid choking the entire VM while one thread is stuck on a slow or non-responsive filesystem: - File.readable? - File.readable_real? - File.writable? - File.writable_real? - File.executable? - File.executable_real? * file.c (nogvl_eaccess): new function (nogvl_access): ditto (rb_access): new wrapper function (rb_eaccess): release GVL (rb_file_readable_real_p): use rb_access (rb_file_writable_real_p): ditto (rb_file_executable_real_p): ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60925 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- file.c | 55 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/file.c b/file.c index 0e8cb5f8f1..31349de5df 100644 --- a/file.c +++ b/file.c @@ -1414,12 +1414,53 @@ eaccess(const char *path, int mode) } #endif +struct access_arg { + const char *path; + int mode; +}; + +static void * +nogvl_eaccess(void *ptr) +{ + struct access_arg *aa = ptr; + + return (void *)(VALUE)eaccess(aa->path, aa->mode); +} + static int rb_eaccess(VALUE fname, int mode) { + struct access_arg aa; + FilePathValue(fname); fname = rb_str_encode_ospath(fname); - return eaccess(StringValueCStr(fname), mode); + aa.path = StringValueCStr(fname); + aa.mode = mode; + + return (int)(VALUE)rb_thread_call_without_gvl(nogvl_eaccess, &aa, + RUBY_UBF_IO, 0); +} + +static void * +nogvl_access(void *ptr) +{ + struct access_arg *aa = ptr; + + return (void *)(VALUE)access(aa->path, aa->mode); +} + +static int +rb_access(VALUE fname, int mode) +{ + struct access_arg aa; + + FilePathValue(fname); + fname = rb_str_encode_ospath(fname); + aa.path = StringValueCStr(fname); + aa.mode = mode; + + return (int)(VALUE)rb_thread_call_without_gvl(nogvl_access, &aa, + RUBY_UBF_IO, 0); } /* @@ -1680,9 +1721,7 @@ rb_file_readable_p(VALUE obj, VALUE fname) static VALUE rb_file_readable_real_p(VALUE obj, VALUE fname) { - FilePathValue(fname); - fname = rb_str_encode_ospath(fname); - if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse; + if (rb_access(fname, R_OK) < 0) return Qfalse; return Qtrue; } @@ -1750,9 +1789,7 @@ rb_file_writable_p(VALUE obj, VALUE fname) static VALUE rb_file_writable_real_p(VALUE obj, VALUE fname) { - FilePathValue(fname); - fname = rb_str_encode_ospath(fname); - if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse; + if (rb_access(fname, W_OK) < 0) return Qfalse; return Qtrue; } @@ -1812,9 +1849,7 @@ rb_file_executable_p(VALUE obj, VALUE fname) static VALUE rb_file_executable_real_p(VALUE obj, VALUE fname) { - FilePathValue(fname); - fname = rb_str_encode_ospath(fname); - if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse; + if (rb_access(fname, X_OK) < 0) return Qfalse; return Qtrue; }