Feature #13958 ยป 0001-Dir.empty-releases-GVL.patch
| 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;
|
||
|
}
|
||
|
-
|
||