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<T> allocator provided by Boehm GC we
can ensure the memory isn't collected. It should be properly freed when
SourceExprCommand goes out of scope.
This commit is contained in:
Andreas Rammhold 2020-04-13 21:09:47 +02:00
parent 512753f824
commit d2c371927e
2 changed files with 10 additions and 4 deletions

View File

@ -41,7 +41,7 @@ private:
std::shared_ptr<EvalState> evalState; std::shared_ptr<EvalState> evalState;
Value * vSourceExpr = 0; std::shared_ptr<Value> vSourceExpr;
}; };
enum RealiseMode { Build, NoBuild, DryRun }; enum RealiseMode { Build, NoBuild, DryRun };

View File

@ -8,10 +8,13 @@
#include "store-api.hh" #include "store-api.hh"
#include "shared.hh" #include "shared.hh"
#include <gc/gc.h>
#include <regex> #include <regex>
namespace nix { namespace nix {
SourceExprCommand::SourceExprCommand() SourceExprCommand::SourceExprCommand()
{ {
mkFlag() mkFlag()
@ -24,11 +27,14 @@ SourceExprCommand::SourceExprCommand()
Value * SourceExprCommand::getSourceExpr(EvalState & state) Value * SourceExprCommand::getSourceExpr(EvalState & state)
{ {
if (vSourceExpr) return vSourceExpr; if (vSourceExpr) return vSourceExpr.get();
auto sToplevel = state.symbols.create("_toplevel"); 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<Value>(traceable_allocator<Value>());
if (file != "") if (file != "")
state.evalFile(lookupFileArg(state, file), *vSourceExpr); state.evalFile(lookupFileArg(state, file), *vSourceExpr);
@ -69,7 +75,7 @@ Value * SourceExprCommand::getSourceExpr(EvalState & state)
vSourceExpr->attrs->sort(); vSourceExpr->attrs->sort();
} }
return vSourceExpr; return vSourceExpr.get();
} }
ref<EvalState> SourceExprCommand::getEvalState() ref<EvalState> SourceExprCommand::getEvalState()