From 987ecca24aa83b2bedc23f18c41385ba3fdeaa4b Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 17 Feb 2026 01:32:13 +0100 Subject: [PATCH] fix(EvalState): Use make_shared for enable_shared_from_this compatibility EvalState inherits from enable_shared_from_this (added in b4c24a29 for debugRepl), but was being stack-allocated or created with make_unique in several places. This causes bad_weak_ptr errors when shared_from_this is called. Convert all EvalState allocations to use make_shared. --- src/libexpr-c/nix_api_expr.cc | 4 +++- src/libexpr-c/nix_api_expr_internal.h | 3 ++- src/libexpr-tests/dynamic-attrs-bench.cc | 3 ++- src/libexpr-tests/get-drvs-bench.cc | 6 ++++-- src/libexpr-tests/regex-cache-bench.cc | 3 ++- src/nix/main.cc | 10 ++++++---- src/nix/nix-build/nix-build.cc | 2 +- src/nix/nix-instantiate/nix-instantiate.cc | 2 +- src/nix/prefetch.cc | 2 +- src/nix/upgrade-nix.cc | 2 +- 10 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/libexpr-c/nix_api_expr.cc b/src/libexpr-c/nix_api_expr.cc index 0dd9fa0a5..61edf9bc3 100644 --- a/src/libexpr-c/nix_api_expr.cc +++ b/src/libexpr-c/nix_api_expr.cc @@ -185,7 +185,9 @@ EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder return EvalState{ .fetchSettings = std::move(builder->fetchSettings), .settings = std::move(builder->settings), - .state = nix::EvalState(builder->lookupPath, builder->store, self->fetchSettings, self->settings), + .statePtr = std::make_shared( + builder->lookupPath, builder->store, self->fetchSettings, self->settings), + .state = *self->statePtr, }; }); } diff --git a/src/libexpr-c/nix_api_expr_internal.h b/src/libexpr-c/nix_api_expr_internal.h index 07c7a2194..633599fb4 100644 --- a/src/libexpr-c/nix_api_expr_internal.h +++ b/src/libexpr-c/nix_api_expr_internal.h @@ -24,7 +24,8 @@ struct EvalState { nix::fetchers::Settings fetchSettings; nix::EvalSettings settings; - nix::EvalState state; + std::shared_ptr statePtr; + nix::EvalState & state; }; struct BindingsBuilder diff --git a/src/libexpr-tests/dynamic-attrs-bench.cc b/src/libexpr-tests/dynamic-attrs-bench.cc index 553d5f9a8..1b1c199bd 100644 --- a/src/libexpr-tests/dynamic-attrs-bench.cc +++ b/src/libexpr-tests/dynamic-attrs-bench.cc @@ -37,7 +37,8 @@ static void BM_EvalDynamicAttrs(benchmark::State & state) EvalSettings evalSettings{readOnlyMode}; evalSettings.nixPath = {}; - EvalState st({}, store, fetchSettings, evalSettings, nullptr); + auto stPtr = std::make_shared(LookupPath{}, store, fetchSettings, evalSettings, nullptr); + auto & st = *stPtr; Expr * expr = st.parseExprFromString(exprStr, st.rootPath(CanonPath::root)); Value v; diff --git a/src/libexpr-tests/get-drvs-bench.cc b/src/libexpr-tests/get-drvs-bench.cc index c6a6fc32c..a5cd59154 100644 --- a/src/libexpr-tests/get-drvs-bench.cc +++ b/src/libexpr-tests/get-drvs-bench.cc @@ -16,7 +16,8 @@ struct GetDerivationsEnv fetchers::Settings fetchSettings{}; bool readOnlyMode = true; EvalSettings evalSettings{readOnlyMode}; - EvalState state; + std::shared_ptr statePtr; + EvalState & state; Bindings * autoArgs = nullptr; Value attrsValue; @@ -27,7 +28,8 @@ struct GetDerivationsEnv settings.nixPath = {}; return settings; }()) - , state({}, store, fetchSettings, evalSettings, nullptr) + , statePtr(std::make_shared(LookupPath{}, store, fetchSettings, evalSettings, nullptr)) + , state(*statePtr) { autoArgs = state.buildBindings(0).finish(); diff --git a/src/libexpr-tests/regex-cache-bench.cc b/src/libexpr-tests/regex-cache-bench.cc index 36a350e2e..2eb17b212 100644 --- a/src/libexpr-tests/regex-cache-bench.cc +++ b/src/libexpr-tests/regex-cache-bench.cc @@ -27,7 +27,8 @@ static void BM_EvalManyBuiltinsMatchSameRegex(benchmark::State & state) EvalSettings evalSettings{readOnlyMode}; evalSettings.nixPath = {}; - EvalState st({}, store, fetchSettings, evalSettings, nullptr); + auto stPtr = std::make_shared(LookupPath{}, store, fetchSettings, evalSettings, nullptr); + auto & st = *stPtr; Expr * expr = st.parseExprFromString(std::string(exprStr), st.rootPath(CanonPath::root)); Value v; diff --git a/src/nix/main.cc b/src/nix/main.cc index dddb757af..63a2846c4 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -247,11 +247,12 @@ static void showHelp(std::vector subcommand, NixArgs & toplevel) evalSettings.restrictEval = true; evalSettings.pureEval = true; - EvalState state( - {}, + auto statePtr = std::make_shared( + LookupPath{}, openStore(StoreReference{.variant = StoreReference::Specified{.scheme = "dummy"}}), fetchSettings, evalSettings); + auto & state = *statePtr; auto vGenerateManpage = state.allocValue(); state.eval( @@ -454,11 +455,12 @@ void mainWrapped(int argc, char ** argv) Xp::FetchTree, }; evalSettings.pureEval = false; - EvalState state( - {}, + auto statePtr = std::make_shared( + LookupPath{}, openStore(StoreReference{.variant = StoreReference::Specified{.scheme = "dummy"}}), fetchSettings, evalSettings); + auto & state = *statePtr; auto builtinsJson = nlohmann::json::object(); for (auto & builtinPtr : state.getBuiltins().attrs()->lexicographicOrder(state.symbols)) { auto & builtin = *builtinPtr; diff --git a/src/nix/nix-build/nix-build.cc b/src/nix/nix-build/nix-build.cc index 13c38f929..441fed025 100644 --- a/src/nix/nix-build/nix-build.cc +++ b/src/nix/nix-build/nix-build.cc @@ -315,7 +315,7 @@ static void main_nix_build(int argc, char ** argv) auto store = openStore(); auto evalStore = myArgs.evalStoreUrl ? openStore(StoreReference{*myArgs.evalStoreUrl}) : store; - auto state = std::make_unique(myArgs.lookupPath, evalStore, fetchSettings, evalSettings, store); + auto state = std::make_shared(myArgs.lookupPath, evalStore, fetchSettings, evalSettings, store); state->repair = myArgs.repair; if (myArgs.repair) buildMode = bmRepair; diff --git a/src/nix/nix-instantiate/nix-instantiate.cc b/src/nix/nix-instantiate/nix-instantiate.cc index 3137e8bc6..31ee5feed 100644 --- a/src/nix/nix-instantiate/nix-instantiate.cc +++ b/src/nix/nix-instantiate/nix-instantiate.cc @@ -169,7 +169,7 @@ static int main_nix_instantiate(int argc, char ** argv) auto store = openStore(); auto evalStore = myArgs.evalStoreUrl ? openStore(StoreReference{*myArgs.evalStoreUrl}) : store; - auto state = std::make_unique(myArgs.lookupPath, evalStore, fetchSettings, evalSettings, store); + auto state = std::make_shared(myArgs.lookupPath, evalStore, fetchSettings, evalSettings, store); state->repair = myArgs.repair; Bindings & autoArgs = *myArgs.getAutoArgs(*state); diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc index 35addff95..074c936a8 100644 --- a/src/nix/prefetch.cc +++ b/src/nix/prefetch.cc @@ -203,7 +203,7 @@ static int main_nix_prefetch_url(int argc, char ** argv) setLogFormat("bar"); auto store = openStore(); - auto state = std::make_unique(myArgs.lookupPath, store, fetchSettings, evalSettings); + auto state = std::make_shared(myArgs.lookupPath, store, fetchSettings, evalSettings); Bindings & autoArgs = *myArgs.getAutoArgs(*state); diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 2dedb53c7..bb7066444 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -182,7 +182,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand auto req = FileTransferRequest(parseURL(upgradeSettings.storePathUrl.get())); auto res = getFileTransfer()->download(req); - auto state = std::make_unique(LookupPath{}, store, fetchSettings, evalSettings); + auto state = std::make_shared(LookupPath{}, store, fetchSettings, evalSettings); auto v = state->allocValue(); state->eval(state->parseExprFromString(res.data, state->rootPath(CanonPath("/no-such-path"))), *v); Bindings & bindings = Bindings::emptyBindings;