Project

General

Profile

Feature #13958 ยป 0001-Dir.empty-releases-GVL.patch

normalperson (Eric Wong), 10/01/2017 04:24 AM

View differences:

dir.c
#include "internal.h"
#include "encindex.h"
#include "ruby/thread.h"
#include <sys/types.h>
#include <sys/stat.h>
......
#else
# define READDIR(dir, enc) readdir((dir))
#endif
/* safe to use without GVL */
static int
to_be_skipped(const struct dirent *dp)
{
......
return rb_file_directory_p(obj, fname);
}
static void *
rb_gc_for_fd_with_gvl(void *ptr)
{
int *e = ptr;
return (void *)(rb_gc_for_fd(*e) ? Qtrue : Qfalse);
}
static void *
nogvl_dir_empty_p(void *ptr)
{
const char *path = ptr;
DIR *dir = opendir(path);
struct dirent *dp;
VALUE result = Qtrue;
if (!dir) {
int e = errno;
switch ((VALUE)rb_thread_call_with_gvl(rb_gc_for_fd_with_gvl, &e)) {
default:
dir = opendir(path);
if (dir) break;
e = errno;
/* fall through */
case 0:
if (e == ENOTDIR) return (void *)Qfalse;
errno = e; /* for rb_sys_fail_path */
return (void *)Qundef;
}
}
while ((dp = READDIR(dir, NULL)) != NULL) {
if (!to_be_skipped(dp)) {
result = Qfalse;
break;
}
}
closedir(dir);
return (void *)result;
}
/*
* call-seq:
* Dir.empty?(path_name) -> true or false
......
static VALUE
rb_dir_s_empty_p(VALUE obj, VALUE dirname)
{
DIR *dir;
struct dirent *dp;
VALUE result = Qtrue, orig;
VALUE result, orig;
const char *path;
enum {false_on_notdir = 1};
......
}
#endif
dir = opendir(path);
if (!dir) {
int e = errno;
switch (rb_gc_for_fd(e)) {
default:
dir = opendir(path);
if (dir) break;
e = errno;
/* fall through */
case 0:
if (false_on_notdir && e == ENOTDIR) return Qfalse;
rb_syserr_fail_path(e, orig);
}
}
errno = 0;
while ((dp = READDIR(dir, NULL)) != NULL) {
if (!to_be_skipped(dp)) {
result = Qfalse;
break;
}
result = (VALUE)rb_thread_call_without_gvl(nogvl_dir_empty_p, (void *)path,
RUBY_UBF_IO, 0);
if (result == Qundef) {
rb_sys_fail_path(orig);
}
closedir(dir);
return result;
}
-
    (1-1/1)