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;
Value * vSourceExpr = 0;
std::shared_ptr<Value> vSourceExpr;
};
enum RealiseMode { Build, NoBuild, DryRun };

View file

@ -8,10 +8,13 @@
#include "store-api.hh"
#include "shared.hh"
#include <gc/gc.h>
#include <regex>
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<Value>(traceable_allocator<Value>());
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<EvalState> SourceExprCommand::getEvalState()