From 746962d7368da4df30b4f51403c383d487ef94d2 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 12 Feb 2016 15:48:29 -0500 Subject: Check the number of open FDs at the start. This fixes the issues with things like $ bfs -empty 3rhs->eval(expr->rhs, state); } -/** - * Infer the number of open file descriptors we're allowed to have. - */ -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}, and allow one free for the predicates - if (ret > 4) { - ret -= 4; - } - - return ret; -} - /** * Type passed as the argument to the bftw() callback. */ @@ -472,11 +451,52 @@ static enum bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) { return state.action; } +/** + * Infer the number of open file descriptors we're allowed to have. + */ +static int infer_fdlimit() { + 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}, and allow an extra fd for the predicates + int nopen = 4; + + // Check /dev/fd for the current number of open fds, if possible (we may + // have inherited more than just the standard ones) + DIR *dir = opendir("/dev/fd"); + if (dir) { + nopen = 0; + + struct dirent *de; + while ((de = readdir(dir)) != NULL) { + if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) { + ++nopen; + } + } + + closedir(dir); + } + + if (ret > nopen) { + ret -= nopen; + } else { + ret = 1; + } + + return ret; +} + /** * Evaluate the command line. */ int eval_cmdline(const struct cmdline *cmdline) { - int nopenfd = infer_nopenfd(); + int nopenfd = infer_fdlimit(); struct callback_args args = { .cmdline = cmdline, -- cgit v1.2.3