[前][次][番号順一覧][スレッド一覧]

ruby-changes:48658

From: normal <ko1@a...>
Date: Wed, 15 Nov 2017 16:24:31 +0900 (JST)
Subject: [ruby-changes:48658] normal:r60774 (trunk): dir.c: revert r60772, r60770, and r60769

normal	2017-11-15 16:24:26 +0900 (Wed, 15 Nov 2017)

  New Revision: 60774

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60774

  Log:
    dir.c: revert r60772, r60770, and r60769
    
    Using readdir(3) without any locking causes thread-safety
    problems if directory streams get shared between threads.  On
    ancient platforms, readdir(3) may have thread-safety problems
    even on different directory streams.
    
    Using readdir_r(3) is not viable, either, as it's deprecated
    due to name overflow problems.
    
    So for now, rely on GVL as in previous Rubies and perhaps
    consider per-"struct dir_data" mutexes for modern platforms
    which allow concurrent calls to readdir(3) on different
    directory streams.

  Modified files:
    trunk/dir.c
Index: dir.c
===================================================================
--- dir.c	(revision 60773)
+++ dir.c	(revision 60774)
@@ -743,23 +743,6 @@ to_be_skipped(const struct dirent *dp) https://github.com/ruby/ruby/blob/trunk/dir.c#L743
     return FALSE;
 }
 
-static void *
-nogvl_readdir(void *ptr)
-{
-    struct dir_data *dirp = ptr;
-
-    return READDIR(dirp->dir, dirp->enc);
-}
-
-static struct dirent *
-readdir_without_gvl(struct dir_data *dirp)
-{
-    if (rb_cThread) /* VM is running */
-	return rb_thread_call_without_gvl(nogvl_readdir, dirp, RUBY_UBF_IO, 0);
-    else
-	return READDIR(dirp->dir, dirp->enc);
-}
-
 /*
  *  call-seq:
  *     dir.read -> string or nil
@@ -780,7 +763,7 @@ dir_read(VALUE dir) https://github.com/ruby/ruby/blob/trunk/dir.c#L763
 
     GetDIR(dir, dirp);
     errno = 0;
-    if ((dp = readdir_without_gvl(dirp))) {
+    if ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
 	return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
     }
     else {
@@ -835,7 +818,7 @@ dir_each_entry(VALUE dir, VALUE (*each)( https://github.com/ruby/ruby/blob/trunk/dir.c#L818
     GetDIR(dir, dirp);
     rewinddir(dirp->dir);
     IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dirp->dir, RSTRING_PTR(dirp->path)));
-    while ((dp = readdir_without_gvl(dirp)) != NULL) {
+    while ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
 	const char *name = dp->d_name;
 	size_t namlen = NAMLEN(dp);
 	VALUE path;
@@ -2023,27 +2006,25 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L2006
     if (pathtype == path_noent) return 0;
 
     if (magical || recursive) {
-	struct dir_data dd;
 	struct dirent *dp;
+	DIR *dirp;
 # if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH
 	char *plainname = 0;
 # endif
 	IF_NORMALIZE_UTF8PATH(int norm_p);
-
-	dd.enc = enc;
 # if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH
 	if (cur + 1 == end && (*cur)->type <= ALPHA) {
 	    plainname = join_path(path, pathlen, dirsep, (*cur)->str, strlen((*cur)->str));
 	    if (!plainname) return -1;
-	    dd.dir = do_opendir(fd, plainname, flags, enc, funcs->error, arg, &status);
+	    dirp = do_opendir(fd, plainname, flags, enc, funcs->error, arg, &status);
 	    GLOB_FREE(plainname);
 	}
 	else
 # else
 	    ;
 # endif
-	dd.dir = do_opendir(fd, *base ? base : ".", flags, enc, funcs->error, arg, &status);
-	if (dd.dir == NULL) {
+	dirp = do_opendir(fd, *base ? base : ".", flags, enc, funcs->error, arg, &status);
+	if (dirp == NULL) {
 # if FNM_SYSCASE || NORMALIZE_UTF8PATH
 	    if ((magical < 2) && !recursive && (errno == EACCES)) {
 		/* no read permission, fallback */
@@ -2052,19 +2033,19 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L2033
 # endif
 	    return status;
 	}
-	IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dd.dir, *base ? base : "."));
+	IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dirp, *base ? base : "."));
 
 # if NORMALIZE_UTF8PATH
 	if (!(norm_p || magical || recursive)) {
-	    closedir(dd.dir);
+	    closedir(dirp);
 	    goto literally;
 	}
 # endif
 # ifdef HAVE_GETATTRLIST
-	if (is_case_sensitive(dd.dir, path) == 0)
+	if (is_case_sensitive(dirp, path) == 0)
 	    flags |= FNM_CASEFOLD;
 # endif
-	while ((dp = readdir_without_gvl(&dd)) != NULL) {
+	while ((dp = READDIR(dirp, enc)) != NULL) {
 	    char *buf;
 	    rb_pathtype_t new_pathtype = path_unknown;
 	    const char *name;
@@ -2159,7 +2140,7 @@ glob_helper( https://github.com/ruby/ruby/blob/trunk/dir.c#L2140
 	    if (status) break;
 	}
 
-	closedir(dd.dir);
+	closedir(dirp);
     }
     else if (plain) {
 	struct glob_pattern **copy_beg, **copy_end, **cur2;

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]