about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndreas Rammhold <andreas@rammhold.de>2020-04-13T19·09+0200
committertazjin <mail@tazj.in>2020-07-17T20·04+0000
commit5218c83b9ff24e15941382e1d065f87d562ba3ac (patch)
tree35a0ec36be7399a8e083887c879a7707ca102053
parent6c98d3d81ffd425882c8ccf74aa5a55494d6c461 (diff)
fix(3p/nix): allocate the vSourceExpr via uncollectable memory r/1352
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.

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 <isomer@tvl.fyi>
-rw-r--r--third_party/nix/src/nix/command.hh4
-rw-r--r--third_party/nix/src/nix/installables.cc11
2 files changed, 10 insertions, 5 deletions
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 <memory>
 #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> evalState;
-
-  Value* vSourceExpr = 0;
+  std::shared_ptr<Value> 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 <regex>
 #include <utility>
 
+#include <gc/gc.h>
+
 #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<Value>(traceable_allocator<Value>());
 
   if (!file.empty()) {
     state.evalFile(lookupFileArg(state, file), *vSourceExpr);
@@ -74,7 +79,7 @@ Value* SourceExprCommand::getSourceExpr(EvalState& state) {
     }
   }
 
-  return vSourceExpr;
+  return vSourceExpr.get();
 }
 
 ref<EvalState> SourceExprCommand::getEvalState() {