From b908f9135cf25151546d8cb0d69778701201494f Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 2 Feb 2026 14:43:35 +0100 Subject: [PATCH] *: only increase stack size if evaluations are done we don't need to mess with this rlimit for e.g. the daemon. increasing the limit later should always be safe since we don't allocate (or map) much before constructing the eval states that ultimately fill our heap and could thus make stack expansion impossible after some time passes. Change-Id: Ieafda537fbc99a6a7f83a093a981e7df947da437 --- lix/libexpr/eval.cc | 6 ++++++ lix/libutil/current-process.cc | 6 +++++- lix/libutil/current-process.hh | 6 ++---- lix/nix/main.cc | 4 ---- subprojects/nix-eval-jobs/src/worker.cc | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 4303e4b70..232614be1 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -4,6 +4,7 @@ #include "lix/libutil/archive.hh" #include "lix/libutil/ansicolor.hh" #include "lix/libutil/async.hh" +#include "lix/libutil/current-process.hh" #include "lix/libutil/deprecated-features.hh" #include "lix/libutil/error.hh" #include "lix/libutil/english.hh" @@ -391,6 +392,11 @@ Evaluator::Evaluator( box_ptr Evaluator::begin(AsyncIoRoot & aio) { assert(!activeEval); + + // Increase the default stack size for the evaluator and for + // libstdc++'s std::regex. + ensureStackSizeAtLeast(64ul * 1024 * 1024); + return box_ptr::unsafeFromNonnull( std::unique_ptr(new EvalState(aio, *this)) ); diff --git a/lix/libutil/current-process.cc b/lix/libutil/current-process.cc index 0c9df5b89..816f96061 100644 --- a/lix/libutil/current-process.cc +++ b/lix/libutil/current-process.cc @@ -54,8 +54,12 @@ unsigned int getMaxCPU() rlim_t savedStackSize = 0; -void setStackSize(rlim_t stackSize) +void ensureStackSizeAtLeast(rlim_t stackSize) { + if (savedStackSize >= stackSize) { + return; + } + struct rlimit limit; if (getrlimit(RLIMIT_STACK, &limit) == 0 && limit.rlim_cur < stackSize) { savedStackSize = limit.rlim_cur; diff --git a/lix/libutil/current-process.hh b/lix/libutil/current-process.hh index 316af234e..42c952de9 100644 --- a/lix/libutil/current-process.hh +++ b/lix/libutil/current-process.hh @@ -14,12 +14,10 @@ namespace nix { */ unsigned int getMaxCPU(); - /** - * Change the stack size. + * Increase the stack size rlimit if it is currently smaller than `stackSize`. */ -void setStackSize(rlim_t stackSize); - +void ensureStackSizeAtLeast(rlim_t stackSize); /** * Restore the original inherited Unix process context (such as signal diff --git a/lix/nix/main.cc b/lix/nix/main.cc index 77e38ee97..3057ff223 100644 --- a/lix/nix/main.cc +++ b/lix/nix/main.cc @@ -665,10 +665,6 @@ int main(int argc, char * * argv) std::abort(); } - // Increase the default stack size for the evaluator and for - // libstdc++'s std::regex. - nix::setStackSize(64ul * 1024 * 1024); - return nix::handleExceptions(argv[0], [&]() { nix::AsyncIoRoot aio; return nix::mainWrapped(aio, argc, argv); diff --git a/subprojects/nix-eval-jobs/src/worker.cc b/subprojects/nix-eval-jobs/src/worker.cc index 29db4fa89..9910a1db2 100644 --- a/subprojects/nix-eval-jobs/src/worker.cc +++ b/subprojects/nix-eval-jobs/src/worker.cc @@ -127,7 +127,7 @@ void worker(nix::AutoCloseFD &to, nix::AutoCloseFD &from, MyArgs &args) try { // Increase the default stack size for the evaluator and for // libstdc++'s std::regex. - nix::setStackSize(64 * 1024 * 1024); + nix::ensureStackSizeAtLeast(64 * 1024 * 1024); #if HAVE_BOEHMGC // We are doing the garbage collection by killing forks.