diff options
Diffstat (limited to 'dir.c')
| -rw-r--r-- | dir.c | 381 |
1 files changed, 276 insertions, 105 deletions
@@ -22,10 +22,6 @@ #include <unistd.h> #endif -#ifndef O_CLOEXEC -# define O_CLOEXEC 0 -#endif - #ifndef USE_OPENDIR_AT # if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD) && \ defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) @@ -35,8 +31,12 @@ # endif #endif -#if USE_OPENDIR_AT -# include <fcntl.h> +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif + +#ifndef O_CLOEXEC +# define O_CLOEXEC 0 #endif #undef HAVE_DIRENT_NAMLEN @@ -113,6 +113,7 @@ char *strchr(char*,char); #include "internal/gc.h" #include "internal/io.h" #include "internal/object.h" +#include "internal/imemo.h" #include "internal/vm.h" #include "ruby/encoding.h" #include "ruby/ruby.h" @@ -142,6 +143,50 @@ char *strchr(char*,char); # define IS_WIN32 0 #endif +#ifdef HAVE_GETATTRLIST +struct getattrlist_args { + const char *path; + int fd; + struct attrlist *list; + void *buf; + size_t size; + unsigned int options; +}; + +# define GETATTRLIST_ARGS(list_, buf_, options_) (struct getattrlist_args) \ + {.list = list_, .buf = buf_, .size = sizeof(buf_), .options = options_} + +static void * +nogvl_getattrlist(void *args) +{ + struct getattrlist_args *arg = args; + return (void *)(VALUE)getattrlist(arg->path, arg->list, arg->buf, arg->size, arg->options); +} + +static int +gvl_getattrlist(struct getattrlist_args *args, const char *path) +{ + args->path = path; + return IO_WITHOUT_GVL_INT(nogvl_getattrlist, args); +} + +# ifdef HAVE_FGETATTRLIST +static void * +nogvl_fgetattrlist(void *args) +{ + struct getattrlist_args *arg = args; + return (void *)(VALUE)fgetattrlist(arg->fd, arg->list, arg->buf, arg->size, arg->options); +} + +static int +gvl_fgetattrlist(struct getattrlist_args *args, int fd) +{ + args->fd = fd; + return IO_WITHOUT_GVL_INT(nogvl_fgetattrlist, args); +} +# endif +#endif + #if NORMALIZE_UTF8PATH # if defined HAVE_FGETATTRLIST || !defined HAVE_GETATTRLIST # define need_normalization(dirp, path) need_normalization(dirp) @@ -154,10 +199,11 @@ need_normalization(DIR *dirp, const char *path) # if defined HAVE_FGETATTRLIST || defined HAVE_GETATTRLIST u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)]; struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,}; + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, 0); # if defined HAVE_FGETATTRLIST - int ret = fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), 0); + int ret = gvl_fgetattrlist(&args, dirfd(dirp)); # else - int ret = getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0); + int ret = gvl_getattrlist(&args, path); # endif if (!ret) { const fsobj_tag_t *tag = (void *)(attrbuf+1); @@ -508,7 +554,7 @@ nogvl_opendir(void *ptr) { const char *path = ptr; - return (void *)opendir(path); + return opendir(path); } static DIR * @@ -519,12 +565,31 @@ opendir_without_gvl(const char *path) u.in = path; - return rb_thread_call_without_gvl(nogvl_opendir, u.out, RUBY_UBF_IO, 0); + return IO_WITHOUT_GVL(nogvl_opendir, u.out); } else return opendir(path); } +static void +close_dir_data(struct dir_data *dp) +{ + if (dp->dir) { + if (closedir(dp->dir) < 0) { + dp->dir = NULL; + rb_sys_fail("closedir"); + } + dp->dir = NULL; + } +} + +static void +check_closedir(DIR *dirp) +{ + if (closedir(dirp) < 0) + rb_sys_fail("closedir"); +} + static VALUE dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc) { @@ -539,8 +604,7 @@ dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc) dirname = rb_str_dup_frozen(dirname); TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dp); - if (dp->dir) closedir(dp->dir); - dp->dir = NULL; + close_dir_data(dp); RB_OBJ_WRITE(dir, &dp->path, Qnil); dp->enc = fsenc; path = RSTRING_PTR(dirname); @@ -554,7 +618,8 @@ dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc) else if (e == EIO) { u_int32_t attrbuf[1]; struct attrlist al = {ATTR_BIT_MAP_COUNT, 0}; - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) { + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, FSOPT_NOFOLLOW); + if (gvl_getattrlist(&args, path) == 0) { dp->dir = opendir_without_gvl(path); } } @@ -587,6 +652,12 @@ dir_s_close(rb_execution_context_t *ec, VALUE klass, VALUE dir) } # if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD) +static void * +nogvl_fdopendir(void *fd) +{ + return fdopendir((int)(VALUE)fd); +} + /* * call-seq: * Dir.for_fd(fd) -> dir @@ -613,7 +684,7 @@ dir_s_for_fd(VALUE klass, VALUE fd) struct dir_data *dp; VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp); - if (!(dp->dir = fdopendir(NUM2INT(fd)))) { + if (!(dp->dir = IO_WITHOUT_GVL(nogvl_fdopendir, (void *)(VALUE)NUM2INT(fd)))) { rb_sys_fail("fdopendir"); UNREACHABLE_RETURN(Qnil); } @@ -755,8 +826,28 @@ fundamental_encoding_p(rb_encoding *enc) } } # define READDIR(dir, enc) rb_w32_readdir((dir), (enc)) +# define READDIR_NOGVL READDIR #else -# define READDIR(dir, enc) readdir((dir)) +NORETURN(static void *sys_failure(void *function)); +static void * +sys_failure(void *function) +{ + rb_sys_fail(function); +} + +static void * +nogvl_readdir(void *dir) +{ + rb_errno_set(0); + if ((dir = readdir(dir)) == NULL) { + if (rb_errno()) + rb_thread_call_with_gvl(sys_failure, (void *)"readdir"); + } + return dir; +} + +# define READDIR(dir, enc) IO_WITHOUT_GVL(nogvl_readdir, (void *)(dir)) +# define READDIR_NOGVL(dir, enc) nogvl_readdir((dir)) #endif /* safe to use without GVL */ @@ -901,7 +992,8 @@ dir_tell(VALUE dir) long pos; GetDIR(dir, dirp); - pos = telldir(dirp->dir); + if((pos = telldir(dirp->dir)) < 0) + rb_sys_fail("telldir"); return rb_int2inum(pos); } #else @@ -1020,8 +1112,7 @@ dir_close(VALUE dir) dirp = dir_get(dir); if (!dirp->dir) return Qnil; - closedir(dirp->dir); - dirp->dir = NULL; + close_dir_data(dirp); return Qnil; } @@ -1037,12 +1128,63 @@ nogvl_chdir(void *ptr) static void dir_chdir0(VALUE path) { - if (chdir(RSTRING_PTR(path)) < 0) + if (IO_WITHOUT_GVL_INT(nogvl_chdir, (void*)RSTRING_PTR(path)) < 0) rb_sys_fail_path(path); } -static int chdir_blocking = 0; -static VALUE chdir_thread = Qnil; +static struct { + VALUE thread; + VALUE path; + int line; + int blocking; +} chdir_lock = { + .blocking = 0, .thread = Qnil, + .path = Qnil, .line = 0, +}; + +static void +chdir_enter(void) +{ + if (chdir_lock.blocking == 0) { + chdir_lock.path = rb_source_location(&chdir_lock.line); + } + chdir_lock.blocking++; + if (NIL_P(chdir_lock.thread)) { + chdir_lock.thread = rb_thread_current(); + } +} + +static void +chdir_leave(void) +{ + chdir_lock.blocking--; + if (chdir_lock.blocking == 0) { + chdir_lock.thread = Qnil; + chdir_lock.path = Qnil; + chdir_lock.line = 0; + } +} + +static int +chdir_alone_block_p(void) +{ + int block_given = rb_block_given_p(); + if (chdir_lock.blocking > 0) { + if (rb_thread_current() != chdir_lock.thread) + rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block"); + if (!block_given) { + if (!NIL_P(chdir_lock.path)) { + rb_warn("conflicting chdir during another chdir block\n" + "%" PRIsVALUE ":%d: note: previous chdir was here", + chdir_lock.path, chdir_lock.line); + } + else { + rb_warn("conflicting chdir during another chdir block"); + } + } + } + return block_given; +} struct chdir_data { VALUE old_path, new_path; @@ -1056,9 +1198,7 @@ chdir_yield(VALUE v) struct chdir_data *args = (void *)v; dir_chdir0(args->new_path); args->done = TRUE; - chdir_blocking++; - if (NIL_P(chdir_thread)) - chdir_thread = rb_thread_current(); + chdir_enter(); return args->yield_path ? rb_yield(args->new_path) : rb_yield_values2(0, NULL); } @@ -1067,9 +1207,7 @@ chdir_restore(VALUE v) { struct chdir_data *args = (void *)v; if (args->done) { - chdir_blocking--; - if (chdir_blocking == 0) - chdir_thread = Qnil; + chdir_leave(); dir_chdir0(args->old_path); } return Qnil; @@ -1078,14 +1216,7 @@ chdir_restore(VALUE v) static VALUE chdir_path(VALUE path, bool yield_path) { - if (chdir_blocking > 0) { - if (rb_thread_current() != chdir_thread) - rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block"); - if (!rb_block_given_p()) - rb_warn("conflicting chdir during another chdir block"); - } - - if (rb_block_given_p()) { + if (chdir_alone_block_p()) { struct chdir_data args; args.old_path = rb_str_encode_ospath(rb_dir_getwd()); @@ -1096,8 +1227,7 @@ chdir_path(VALUE path, bool yield_path) } else { char *p = RSTRING_PTR(path); - int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_chdir, p, - RUBY_UBF_IO, 0); + int r = IO_WITHOUT_GVL_INT(nogvl_chdir, p); if (r < 0) rb_sys_fail_path(path); } @@ -1200,7 +1330,7 @@ nogvl_fchdir(void *ptr) static void dir_fchdir(int fd) { - if (fchdir(fd) < 0) + if (IO_WITHOUT_GVL_INT(nogvl_fchdir, (void *)&fd) < 0) rb_sys_fail("fchdir"); } @@ -1216,9 +1346,7 @@ fchdir_yield(VALUE v) struct fchdir_data *args = (void *)v; dir_fchdir(args->fd); args->done = TRUE; - chdir_blocking++; - if (NIL_P(chdir_thread)) - chdir_thread = rb_thread_current(); + chdir_enter(); return rb_yield_values(0); } @@ -1227,9 +1355,7 @@ fchdir_restore(VALUE v) { struct fchdir_data *args = (void *)v; if (args->done) { - chdir_blocking--; - if (chdir_blocking == 0) - chdir_thread = Qnil; + chdir_leave(); dir_fchdir(RB_NUM2INT(dir_fileno(args->old_dir))); } dir_close(args->old_dir); @@ -1293,14 +1419,7 @@ dir_s_fchdir(VALUE klass, VALUE fd_value) { int fd = RB_NUM2INT(fd_value); - if (chdir_blocking > 0) { - if (rb_thread_current() != chdir_thread) - rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block"); - if (!rb_block_given_p()) - rb_warn("conflicting chdir during another chdir block"); - } - - if (rb_block_given_p()) { + if (chdir_alone_block_p()) { struct fchdir_data args; args.old_dir = dir_s_alloc(klass); dir_initialize(NULL, args.old_dir, rb_fstring_cstr("."), Qnil); @@ -1309,8 +1428,7 @@ dir_s_fchdir(VALUE klass, VALUE fd_value) return rb_ensure(fchdir_yield, (VALUE)&args, fchdir_restore, (VALUE)&args); } else { - int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_fchdir, &fd, - RUBY_UBF_IO, 0); + int r = IO_WITHOUT_GVL_INT(nogvl_fchdir, &fd); if (r < 0) rb_sys_fail("fchdir"); } @@ -1362,19 +1480,15 @@ rb_dir_getwd_ospath(void) VALUE cwd; VALUE path_guard; -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 - path_guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL); + path_guard = rb_imemo_tmpbuf_new(); path = ruby_getcwd(); - DATA_PTR(path_guard) = path; + rb_imemo_tmpbuf_set_ptr(path_guard, path); #ifdef __APPLE__ cwd = rb_str_normalize_ospath(path, strlen(path)); #else cwd = rb_str_new2(path); #endif - DATA_PTR(path_guard) = 0; - - xfree(path); + rb_free_tmp_buffer(&path_guard); return cwd; } #endif @@ -1436,6 +1550,12 @@ check_dirname(VALUE dir) } #if defined(HAVE_CHROOT) +static void * +nogvl_chroot(void *dirname) +{ + return (void *)(VALUE)chroot((const char *)dirname); +} + /* * call-seq: * Dir.chroot(dirpath) -> 0 @@ -1452,7 +1572,7 @@ static VALUE dir_s_chroot(VALUE dir, VALUE path) { path = check_dirname(path); - if (chroot(RSTRING_PTR(path)) == -1) + if (IO_WITHOUT_GVL_INT(nogvl_chroot, (void *)RSTRING_PTR(path)) == -1) rb_sys_fail_path(path); return INT2FIX(0); @@ -1506,7 +1626,7 @@ dir_s_mkdir(int argc, VALUE *argv, VALUE obj) path = check_dirname(path); m.path = RSTRING_PTR(path); - r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_mkdir, &m, RUBY_UBF_IO, 0); + r = IO_WITHOUT_GVL_INT(nogvl_mkdir, &m); if (r < 0) rb_sys_fail_path(path); @@ -1539,7 +1659,7 @@ dir_s_rmdir(VALUE obj, VALUE dir) dir = check_dirname(dir); p = RSTRING_PTR(dir); - r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_rmdir, (void *)p, RUBY_UBF_IO, 0); + r = IO_WITHOUT_GVL_INT(nogvl_rmdir, (void *)p); if (r < 0) rb_sys_fail_path(dir); @@ -1629,11 +1749,11 @@ to_be_ignored(int e) } #ifdef _WIN32 -#define STAT(p, s) rb_w32_ustati128((p), (s)) -#undef lstat -#define lstat(p, s) rb_w32_ulstati128((p), (s)) +#define STAT(args) (int)(VALUE)nogvl_stat(&(args)) +#define LSTAT(args) (int)(VALUE)nogvl_lstat(&(args)) #else -#define STAT(p, s) stat((p), (s)) +#define STAT(args) IO_WITHOUT_GVL_INT(nogvl_stat, (void *)&(args)) +#define LSTAT(args) IO_WITHOUT_GVL_INT(nogvl_lstat, (void *)&(args)) #endif typedef int ruby_glob_errfunc(const char*, VALUE, const void*, int); @@ -1654,14 +1774,50 @@ at_subpath(int fd, size_t baselen, const char *path) return *path ? path : "."; } +#if USE_OPENDIR_AT +struct fstatat_args { + int fd; + int flag; + const char *path; + struct stat *pst; +}; + +static void * +nogvl_fstatat(void *args) +{ + struct fstatat_args *arg = (struct fstatat_args *)args; + return (void *)(VALUE)fstatat(arg->fd, arg->path, arg->pst, arg->flag); +} +#else +struct stat_args { + const char *path; + struct stat *pst; +}; + +static void * +nogvl_stat(void *args) +{ + struct stat_args *arg = (struct stat_args *)args; + return (void *)(VALUE)stat(arg->path, arg->pst); +} +#endif + /* System call with warning */ static int do_stat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, rb_encoding *enc) { #if USE_OPENDIR_AT - int ret = fstatat(fd, at_subpath(fd, baselen, path), pst, 0); + struct fstatat_args args; + args.fd = fd; + args.path = path; + args.pst = pst; + args.flag = 0; + int ret = IO_WITHOUT_GVL_INT(nogvl_fstatat, (void *)&args); #else - int ret = STAT(path, pst); + struct stat_args args; + args.path = path; + args.pst = pst; + int ret = STAT(args); #endif if (ret < 0 && !to_be_ignored(errno)) sys_warning(path, enc); @@ -1670,13 +1826,30 @@ do_stat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, r } #if defined HAVE_LSTAT || defined lstat || USE_OPENDIR_AT +#if !USE_OPENDIR_AT +static void * +nogvl_lstat(void *args) +{ + struct stat_args *arg = (struct stat_args *)args; + return (void *)(VALUE)lstat(arg->path, arg->pst); +} +#endif + static int do_lstat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, rb_encoding *enc) { #if USE_OPENDIR_AT - int ret = fstatat(fd, at_subpath(fd, baselen, path), pst, AT_SYMLINK_NOFOLLOW); + struct fstatat_args args; + args.fd = fd; + args.path = path; + args.pst = pst; + args.flag = AT_SYMLINK_NOFOLLOW; + int ret = IO_WITHOUT_GVL_INT(nogvl_fstatat, (void *)&args); #else - int ret = lstat(path, pst); + struct stat_args args; + args.path = path; + args.pst = pst; + int ret = LSTAT(args); #endif if (ret < 0 && !to_be_ignored(errno)) sys_warning(path, enc); @@ -1758,7 +1931,7 @@ opendir_at(int basefd, const char *path) oaa.path = path; if (vm_initialized) - return rb_thread_call_without_gvl(nogvl_opendir_at, &oaa, RUBY_UBF_IO, 0); + return IO_WITHOUT_GVL(nogvl_opendir_at, &oaa); else return nogvl_opendir_at(&oaa); } @@ -2037,14 +2210,15 @@ is_case_sensitive(DIR *dirp, const char *path) const vol_capabilities_attr_t *const cap = attrbuf[0].cap; const int idx = VOL_CAPABILITIES_FORMAT; const uint32_t mask = VOL_CAP_FMT_CASE_SENSITIVE; - + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, FSOPT_NOFOLLOW); # if defined HAVE_FGETATTRLIST - if (fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) - return -1; + int ret = gvl_fgetattrlist(&args, dirfd(dirp)); # else - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) - return -1; + int ret = gvl_getattrlist(&args, path); # endif + if (ret) + return -1; + if (!(cap->valid[idx] & mask)) return -1; return (cap->capabilities[idx] & mask) != 0; @@ -2067,7 +2241,8 @@ replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int f IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil); *type = path_noent; - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) { + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, FSOPT_NOFOLLOW); + if (gvl_getattrlist(&args, path)) { if (!to_be_ignored(errno)) sys_warning(path, enc); return path; @@ -2440,7 +2615,7 @@ static void glob_dir_finish(ruby_glob_entries_t *ent, int flags) { if (flags & FNM_GLOB_NOSORT) { - closedir(ent->nosort.dirp); + check_closedir(ent->nosort.dirp); ent->nosort.dirp = NULL; } else if (ent->sort.entries) { @@ -2471,7 +2646,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc) #ifdef _WIN32 if ((capacity = dirp->nfiles) > 0) { if (!(newp = GLOB_ALLOC_N(rb_dirent_t, capacity))) { - closedir(dirp); + check_closedir(dirp); return NULL; } ent->sort.entries = newp; @@ -2491,7 +2666,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc) ent->sort.entries[count++] = rdp; ent->sort.count = count; } - closedir(dirp); + check_closedir(dirp); if (count < capacity) { if (!(newp = GLOB_REALLOC_N(ent->sort.entries, count))) { glob_dir_finish(ent, 0); @@ -2506,7 +2681,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc) nomem: glob_dir_finish(ent, 0); - closedir(dirp); + check_closedir(dirp); return NULL; } @@ -2669,7 +2844,7 @@ glob_helper( # if NORMALIZE_UTF8PATH if (!(norm_p || magical || recursive)) { - closedir(dirp); + check_closedir(dirp); goto literally; } # endif @@ -3492,7 +3667,7 @@ file_s_fnmatch(int argc, VALUE *argv, VALUE obj) * call-seq: * Dir.home(user_name = nil) -> dirpath * - * Retruns the home directory path of the user specified with +user_name+ + * Returns the home directory path of the user specified with +user_name+ * if it is not +nil+, or the current login user: * * Dir.home # => "/home/me" @@ -3561,13 +3736,13 @@ nogvl_dir_empty_p(void *ptr) return (void *)INT2FIX(e); } } - while ((dp = READDIR(dir, NULL)) != NULL) { + while ((dp = READDIR_NOGVL(dir, NULL)) != NULL) { if (!to_be_skipped(dp)) { result = Qfalse; break; } } - closedir(dir); + check_closedir(dir); return (void *)result; } @@ -3603,12 +3778,13 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname) { u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)]; struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,}; - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) != 0) + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, 0); + if (gvl_getattrlist(&args, path) != 0) rb_sys_fail_path(orig); if (*(const fsobj_tag_t *)(attrbuf+1) == VT_HFS) { al.commonattr = 0; al.dirattr = ATTR_DIR_ENTRYCOUNT; - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) == 0) { + if (gvl_getattrlist(&args, path) == 0) { if (attrbuf[0] >= 2 * sizeof(u_int32_t)) return RBOOL(attrbuf[1] == 0); if (false_on_notdir) return Qfalse; @@ -3618,8 +3794,7 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname) } #endif - result = (VALUE)rb_thread_call_without_gvl(nogvl_dir_empty_p, (void *)path, - RUBY_UBF_IO, 0); + result = (VALUE)IO_WITHOUT_GVL(nogvl_dir_empty_p, (void *)path); if (FIXNUM_P(result)) { rb_syserr_fail_path((int)FIX2LONG(result), orig); } @@ -3629,6 +3804,9 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname) void Init_Dir(void) { + rb_gc_register_address(&chdir_lock.path); + rb_gc_register_address(&chdir_lock.thread); + rb_cDir = rb_define_class("Dir", rb_cObject); rb_include_module(rb_cDir, rb_mEnumerable); @@ -3673,26 +3851,19 @@ Init_Dir(void) rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1); rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1); - /* Document-const: FNM_NOESCAPE - * {File::FNM_NOESCAPE}[rdoc-ref:File::Constants@File-3A-3AFNM_NOESCAPE] */ + /* {File::FNM_NOESCAPE}[rdoc-ref:File::Constants@File-3A-3AFNM_NOESCAPE] */ rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE)); - /* Document-const: FNM_PATHNAME - * {File::FNM_PATHNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_PATHNAME] */ + /* {File::FNM_PATHNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_PATHNAME] */ rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME)); - /* Document-const: FNM_DOTMATCH - * {File::FNM_DOTMATCH}[rdoc-ref:File::Constants@File-3A-3AFNM_DOTMATCH] */ + /* {File::FNM_DOTMATCH}[rdoc-ref:File::Constants@File-3A-3AFNM_DOTMATCH] */ rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH)); - /* Document-const: FNM_CASEFOLD - * {File::FNM_CASEFOLD}[rdoc-ref:File::Constants@File-3A-3AFNM_CASEFOLD] */ + /* {File::FNM_CASEFOLD}[rdoc-ref:File::Constants@File-3A-3AFNM_CASEFOLD] */ rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD)); - /* Document-const: FNM_EXTGLOB - * {File::FNM_EXTGLOB}[rdoc-ref:File::Constants@File-3A-3AFNM_EXTGLOB] */ + /* {File::FNM_EXTGLOB}[rdoc-ref:File::Constants@File-3A-3AFNM_EXTGLOB] */ rb_file_const("FNM_EXTGLOB", INT2FIX(FNM_EXTGLOB)); - /* Document-const: FNM_SYSCASE - * {File::FNM_SYSCASE}[rdoc-ref:File::Constants@File-3A-3AFNM_SYSCASE] */ + /* {File::FNM_SYSCASE}[rdoc-ref:File::Constants@File-3A-3AFNM_SYSCASE] */ rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE)); - /* Document-const: FNM_SHORTNAME - * {File::FNM_SHORTNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_SHORTNAME] */ + /* {File::FNM_SHORTNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_SHORTNAME] */ rb_file_const("FNM_SHORTNAME", INT2FIX(FNM_SHORTNAME)); } |
