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
This commit is contained in:
normal 2017-11-28 03:28:35 +00:00
Родитель d7a38817da
Коммит 17dd212f00
1 изменённых файлов: 45 добавлений и 10 удалений

55
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;
}