From 5218c83b9ff24e15941382e1d065f87d562ba3ac Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Mon, 13 Apr 2020 21:09:47 +0200 Subject: fix(3p/nix): 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. Backported from: https://github.com/NixOS/nix/commit/d2c371927e45c1d4e4f7e4ad331a3f68d67d5469 Change-Id: I1f7c745dbc66c7164bee50f4d9b0d437dbc7dd51 Reviewed-on: https://cl.tvl.fyi/c/depot/+/1251 Tested-by: BuildkiteCI Reviewed-by: isomer --- third_party/nix/src/nix/command.hh | 4 ++-- third_party/nix/src/nix/installables.cc | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'third_party/nix') diff --git a/third_party/nix/src/nix/command.hh b/third_party/nix/src/nix/command.hh index 813fdb557d82..f7eaeb721620 100644 --- a/third_party/nix/src/nix/command.hh +++ b/third_party/nix/src/nix/command.hh @@ -1,5 +1,6 @@ #pragma once +#include #include "libexpr/common-eval-args.hh" #include "libutil/args.hh" @@ -80,8 +81,7 @@ struct SourceExprCommand : virtual Args, StoreCommand, MixEvalArgs { private: std::shared_ptr evalState; - - Value* vSourceExpr = 0; + std::shared_ptr vSourceExpr; }; enum RealiseMode { Build, NoBuild, DryRun }; diff --git a/third_party/nix/src/nix/installables.cc b/third_party/nix/src/nix/installables.cc index 80c5ddb68b9c..cc001d37f327 100644 --- a/third_party/nix/src/nix/installables.cc +++ b/third_party/nix/src/nix/installables.cc @@ -1,6 +1,8 @@ #include #include +#include + #include "libexpr/attr-path.hh" #include "libexpr/common-eval-args.hh" #include "libexpr/eval-inline.hh" @@ -24,12 +26,15 @@ SourceExprCommand::SourceExprCommand() { Value* SourceExprCommand::getSourceExpr(EvalState& state) { if (vSourceExpr != nullptr) { - return 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.empty()) { state.evalFile(lookupFileArg(state, file), *vSourceExpr); @@ -74,7 +79,7 @@ Value* SourceExprCommand::getSourceExpr(EvalState& state) { } } - return vSourceExpr; + return vSourceExpr.get(); } ref SourceExprCommand::getEvalState() { -- cgit 1.4.1