diff options
-rw-r--r-- | src/ctx.c | 6 | ||||
-rw-r--r-- | src/ctx.h | 8 | ||||
-rw-r--r-- | src/eval.c | 33 | ||||
-rw-r--r-- | src/eval.h | 2 | ||||
-rw-r--r-- | src/exec.c | 26 |
5 files changed, 38 insertions, 37 deletions
@@ -30,12 +30,10 @@ struct bfs_ctx *bfs_ctx_new(void) { trie_init(&ctx->files); - struct rlimit rl; - if (getrlimit(RLIMIT_NOFILE, &rl) != 0) { + if (getrlimit(RLIMIT_NOFILE, &ctx->orig_nofile) != 0) { goto fail; } - ctx->nofile_soft = rl.rlim_cur; - ctx->nofile_hard = rl.rlim_max; + ctx->cur_nofile = ctx->orig_nofile; ctx->users = bfs_users_new(); if (!ctx->users) { @@ -87,10 +87,10 @@ struct bfs_ctx { /** The number of files owned by the context. */ int nfiles; - /** The initial RLIMIT_NOFILE soft limit. */ - rlim_t nofile_soft; - /** The initial RLIMIT_NOFILE hard limit. */ - rlim_t nofile_hard; + /** The initial RLIMIT_NOFILE limits. */ + struct rlimit orig_nofile; + /** The current RLIMIT_NOFILE limits. */ + struct rlimit cur_nofile; /** The current time. */ struct timespec now; @@ -1428,25 +1428,30 @@ done: } /** Raise RLIMIT_NOFILE if possible, and return the new limit. */ -static int raise_fdlimit(const struct bfs_ctx *ctx) { +static int raise_fdlimit(struct bfs_ctx *ctx) { + rlim_t cur = ctx->orig_nofile.rlim_cur; + rlim_t max = ctx->orig_nofile.rlim_max; + rlim_t target = 64 << 10; - if (rlim_cmp(target, ctx->nofile_hard) > 0) { - target = ctx->nofile_hard; + if (rlim_cmp(target, max) > 0) { + target = max; } - int ret = target; + if (rlim_cmp(target, cur) <= 0) { + return target; + } - if (rlim_cmp(target, ctx->nofile_soft) > 0) { - const struct rlimit rl = { - .rlim_cur = target, - .rlim_max = ctx->nofile_hard, - }; - if (setrlimit(RLIMIT_NOFILE, &rl) != 0) { - ret = ctx->nofile_soft; - } + const struct rlimit rl = { + .rlim_cur = target, + .rlim_max = max, + }; + + if (setrlimit(RLIMIT_NOFILE, &rl) != 0) { + return cur; } - return ret; + ctx->cur_nofile = rl; + return target; } /** Preallocate the fd table in the kernel. */ @@ -1581,7 +1586,7 @@ static bool eval_must_buffer(const struct bfs_expr *expr) { return false; } -int bfs_eval(const struct bfs_ctx *ctx) { +int bfs_eval(struct bfs_ctx *ctx) { if (!ctx->expr) { return EXIT_SUCCESS; } @@ -39,7 +39,7 @@ typedef bool bfs_eval_fn(const struct bfs_expr *expr, struct bfs_eval *state); * @return * EXIT_SUCCESS on success, otherwise on failure. */ -int bfs_eval(const struct bfs_ctx *ctx); +int bfs_eval(struct bfs_ctx *ctx); // Predicate evaluation functions @@ -327,8 +327,10 @@ static void bfs_exec_closewd(struct bfs_exec *execbuf, const struct BFTW *ftwbuf /** Actually spawn the process. */ static int bfs_exec_spawn(const struct bfs_exec *execbuf) { + const struct bfs_ctx *ctx = execbuf->ctx; + // Flush the context state for consistency with the external process - bfs_ctx_flush(execbuf->ctx); + bfs_ctx_flush(ctx); if (execbuf->flags & BFS_EXEC_CONFIRM) { for (size_t i = 0; i < execbuf->argc; ++i) { @@ -356,34 +358,30 @@ static int bfs_exec_spawn(const struct bfs_exec *execbuf) { pid_t pid = -1; int error; - struct bfs_spawn ctx; - if (bfs_spawn_init(&ctx) != 0) { + struct bfs_spawn spawn; + if (bfs_spawn_init(&spawn) != 0) { return -1; } - if (bfs_spawn_setflags(&ctx, BFS_SPAWN_USEPATH) != 0) { + if (bfs_spawn_setflags(&spawn, BFS_SPAWN_USEPATH) != 0) { goto fail; } // Reset RLIMIT_NOFILE, to avoid breaking applications that use select() - struct rlimit rl = { - .rlim_cur = execbuf->ctx->nofile_soft, - .rlim_max = execbuf->ctx->nofile_hard, - }; - if (bfs_spawn_addsetrlimit(&ctx, RLIMIT_NOFILE, &rl) != 0) { + if (bfs_spawn_addsetrlimit(&spawn, RLIMIT_NOFILE, &ctx->orig_nofile) != 0) { goto fail; } if (execbuf->wd_fd >= 0) { - if (bfs_spawn_addfchdir(&ctx, execbuf->wd_fd) != 0) { + if (bfs_spawn_addfchdir(&spawn, execbuf->wd_fd) != 0) { goto fail; } } - pid = bfs_spawn(execbuf->argv[0], &ctx, execbuf->argv, NULL); + pid = bfs_spawn(execbuf->argv[0], &spawn, execbuf->argv, NULL); fail: error = errno; - bfs_spawn_destroy(&ctx); + bfs_spawn_destroy(&spawn); if (pid < 0) { errno = error; return -1; @@ -409,9 +407,9 @@ fail: if (!str) { str = "unknown"; } - bfs_warning(execbuf->ctx, "Command '${ex}%s${rs}' terminated by signal %d (%s)\n", execbuf->argv[0], sig, str); + bfs_warning(ctx, "Command '${ex}%s${rs}' terminated by signal %d (%s)\n", execbuf->argv[0], sig, str); } else { - bfs_warning(execbuf->ctx, "Command '${ex}%s${rs}' terminated abnormally\n", execbuf->argv[0]); + bfs_warning(ctx, "Command '${ex}%s${rs}' terminated abnormally\n", execbuf->argv[0]); } errno = 0; |