From af7878c7474de2f6c5542ad52a0a67237387c638 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 12 Nov 2017 15:16:23 -0500 Subject: cmdline: Account for files opened during/between evaluations more carefully --- cmdline.h | 4 ++++ eval.c | 3 +-- parse.c | 28 +++++++++++++++++++++------- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/cmdline.h b/cmdline.h index e9731f9..09500ce 100644 --- a/cmdline.h +++ b/cmdline.h @@ -98,6 +98,10 @@ struct cmdline { struct open_file *open_files; /** The number of open files owned by the command line. */ int nopen_files; + /** The number of files that may stay open between evaluations. */ + int persistent_fds; + /** The number of files that mau be opened during evaluations. */ + int ephemeral_fds; }; /** diff --git a/eval.c b/eval.c index fe89225..1c9ae50 100644 --- a/eval.c +++ b/eval.c @@ -1191,8 +1191,7 @@ static int infer_fdlimit(const struct cmdline *cmdline) { closedir(dir); } - // 1 extra fd needed by -empty - ret -= nopen + 1; + ret -= nopen + cmdline->persistent_fds + cmdline->ephemeral_fds; // bftw() needs at least 2 available fds if (ret < 2) { diff --git a/parse.c b/parse.c index 9d533ab..9054af7 100644 --- a/parse.c +++ b/parse.c @@ -1064,13 +1064,19 @@ static struct expr *parse_empty(struct parser_state *state, int arg1, int arg2) expr->cost = 2000.0; expr->probability = 0.01; - if (state->cmdline->optlevel < 4) { + struct cmdline *cmdline = state->cmdline; + + if (cmdline->optlevel < 4) { // Since -empty attempts to open and read directories, it may // have side effects such as reporting permission errors, and // thus shouldn't be re-ordered without aggressive optimizations expr->pure = false; } + if (cmdline->ephemeral_fds < 1) { + cmdline->ephemeral_fds = 1; + } + return expr; } @@ -1078,28 +1084,34 @@ static struct expr *parse_empty(struct parser_state *state, int arg1, int arg2) * Parse -exec(dir)?/-ok(dir)?. */ static struct expr *parse_exec(struct parser_state *state, int flags, int arg2) { - struct bfs_exec *execbuf = parse_bfs_exec(state->argv, flags, state->cmdline); + struct cmdline *cmdline = state->cmdline; + + struct bfs_exec *execbuf = parse_bfs_exec(state->argv, flags, cmdline); if (!execbuf) { return NULL; } - if ((execbuf->flags & BFS_EXEC_CHDIR) && (execbuf->flags & BFS_EXEC_MULTI)) { - ++state->cmdline->nopen_files; - } - struct expr *expr = parse_action(state, eval_exec, execbuf->tmpl_argc + 2); if (!expr) { free_bfs_exec(execbuf); return NULL; } + expr->execbuf = execbuf; + if (execbuf->flags & BFS_EXEC_MULTI) { expr_set_always_true(expr); } else { expr->cost = 1000000.0; } - expr->execbuf = execbuf; + if (execbuf->flags & BFS_EXEC_CHDIR) { + if (execbuf->flags & BFS_EXEC_MULTI) { + ++cmdline->persistent_fds; + } else if (cmdline->ephemeral_fds < 1) { + cmdline->ephemeral_fds = 1; + } + } return expr; } @@ -3035,6 +3047,8 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) { cmdline->expr = &expr_true; cmdline->open_files = NULL; cmdline->nopen_files = 0; + cmdline->persistent_fds = 0; + cmdline->ephemeral_fds = 0; cmdline->argv = malloc((argc + 1)*sizeof(*cmdline->argv)); if (!cmdline->argv) { -- cgit v1.2.3