From e7cb622ee5cf2cc1c019374c3911d9c70083701d Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 27 Jul 2015 16:31:35 -0400 Subject: Infer the right value for nopenfd, and recover from EMFILE. --- bfs.c | 23 +++++++++++++++++++++-- bftw.c | 14 +++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/bfs.c b/bfs.c index fcd1383..6bbfa05 100644 --- a/bfs.c +++ b/bfs.c @@ -15,8 +15,27 @@ #include #include #include +#include #include +static int infer_nopenfd() { + int ret = 4096; + + struct rlimit rl; + if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { + if (rl.rlim_cur != RLIM_INFINITY) { + ret = rl.rlim_cur; + } + } + + // Account for std{in,out,err} + if (ret > 3) { + ret -= 3; + } + + return ret; +} + typedef struct { const char *path; color_table *colors; @@ -85,8 +104,8 @@ int main(int argc, char *argv[]) { opts.colors = parse_colors(getenv("LS_COLORS")); } - // TODO: getrlimit(RLIMIT_NOFILE) - if (bftw(opts.path, callback, 1024, flags, &opts) != 0) { + int nopenfd = infer_nopenfd(); + if (bftw(opts.path, callback, nopenfd, flags, &opts) != 0) { perror("bftw()"); goto done; } diff --git a/bftw.c b/bftw.c index 31e6fe2..75a208c 100644 --- a/bftw.c +++ b/bftw.c @@ -291,7 +291,19 @@ static DIR *dircache_entry_open(dircache *cache, dircache_entry *entry, const ch fd = dirfd(base->dir); } - DIR *dir = opendirat(fd, path + nameoff); + const char *relpath = path + nameoff; + DIR *dir = opendirat(fd, relpath); + + if (!dir + && errno == EMFILE + && cache->lru_tail + && cache->lru_tail != base) { + // Too many open files, shrink the LRU cache + dircache_entry_close(cache, cache->lru_tail); + --cache->lru_remaining; + dir = opendirat(fd, relpath); + } + if (dir) { entry->dir = dir; dircache_lru_add(cache, entry); -- cgit v1.2.3