From d2c371927e45c1d4e4f7e4ad331a3f68d67d5469 Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Mon, 13 Apr 2020 21:09:47 +0200 Subject: [PATCH] SourceExprCommand: allocate the vSourceExpr via uncollectable memory Previously the memory would occasionally be collected during eval since the GC doesn't consider the member variable as alive / doesn't scan the region of memory where the pointer lives. By using the traceable_allocator allocator provided by Boehm GC we can ensure the memory isn't collected. It should be properly freed when SourceExprCommand goes out of scope. --- src/nix/command.hh | 2 +- src/nix/installables.cc | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/nix/command.hh b/src/nix/command.hh index 23f5c9898..2c2303208 100644 --- a/src/nix/command.hh +++ b/src/nix/command.hh @@ -41,7 +41,7 @@ private: std::shared_ptr evalState; - Value * vSourceExpr = 0; + std::shared_ptr vSourceExpr; }; enum RealiseMode { Build, NoBuild, DryRun }; diff --git a/src/nix/installables.cc b/src/nix/installables.cc index f464d0aa1..902383bff 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -8,10 +8,13 @@ #include "store-api.hh" #include "shared.hh" +#include + #include namespace nix { + SourceExprCommand::SourceExprCommand() { mkFlag() @@ -24,11 +27,14 @@ SourceExprCommand::SourceExprCommand() Value * SourceExprCommand::getSourceExpr(EvalState & state) { - if (vSourceExpr) return vSourceExpr; + if (vSourceExpr) return vSourceExpr.get(); auto sToplevel = state.symbols.create("_toplevel"); - vSourceExpr = state.allocValue(); + // Allocate the vSourceExpr Value as uncollectable. Boehm GC doesn't + // consider the member variable "alive" during execution causing it to be + // GC'ed in the middle of evaluation. + vSourceExpr = std::allocate_shared(traceable_allocator()); if (file != "") state.evalFile(lookupFileArg(state, file), *vSourceExpr); @@ -69,7 +75,7 @@ Value * SourceExprCommand::getSourceExpr(EvalState & state) vSourceExpr->attrs->sort(); } - return vSourceExpr; + return vSourceExpr.get(); } ref SourceExprCommand::getEvalState()