summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--dir.c15
-rw-r--r--test/ruby/test_dir.rb14
3 files changed, 32 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index bab1afbdd0..72fd643356 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Fri Oct 21 16:44:44 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (do_opendir): retry after GC when the limit for open file
+ descriptors reached.
+
Fri Oct 21 16:06:25 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ruby.c (open_load_file): retry after GC when the limit for open
diff --git a/dir.c b/dir.c
index cf4daeecf1..b2d88031e7 100644
--- a/dir.c
+++ b/dir.c
@@ -1286,8 +1286,19 @@ do_opendir(const char *path, int flags, rb_encoding *enc)
}
#endif
dirp = opendir(path);
- if (dirp == NULL && !to_be_ignored(errno))
- sys_warning(path, enc);
+ if (!dirp) {
+ int e = errno;
+ switch (rb_gc_for_fd(e)) {
+ default:
+ dirp = opendir(path);
+ if (dirp) break;
+ e = errno;
+ /* fallback */
+ case 0:
+ if (to_be_ignored(e)) break;
+ sys_warning(path, enc);
+ }
+ }
#ifdef _WIN32
if (tmp) rb_str_resize(tmp, 0); /* GC guard */
#endif
diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb
index b188f4da60..ed0d084528 100644
--- a/test/ruby/test_dir.rb
+++ b/test/ruby/test_dir.rb
@@ -354,4 +354,18 @@ class TestDir < Test::Unit::TestCase
assert_raise(Errno::ENOENT) {Dir.empty?(@nodir)}
assert_not_send([Dir, :empty?, File.join(@root, "b")])
end
+
+ def test_glob_gc_for_fd
+ assert_separately(["-C", @root], "#{<<-"begin;"}\n#{<<-"end;"}", timeout: 3)
+ begin;
+ Process.setrlimit(Process::RLIMIT_NOFILE, 50)
+ begin
+ tap {tap {tap {(0..100).map {open(IO::NULL)}}}}
+ rescue Errno::EMFILE
+ end
+ list = Dir.glob("*").sort
+ assert_not_empty(list)
+ assert_equal([*"a".."z"], list)
+ end;
+ end
end