about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2015-03-19T19·02+0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2015-03-19T19·02+0100
commit726f7f7fc92f4914bca450a37b8b85b1018afc01 (patch)
tree7e484a7a0249b9ae3fda87347568a0b77505335b
parentda6b704b197f19c386f0e53f5553252a226650bb (diff)
Fix Boehm API violation
We were calling GC_INIT() after doing an allocation (in the baseEnv
construction), which is not allowed.
-rw-r--r--src/libexpr/eval.cc80
-rw-r--r--src/libexpr/eval.hh4
-rw-r--r--src/nix-env/nix-env.cc1
-rw-r--r--src/nix-instantiate/nix-instantiate.cc1
4 files changed, 48 insertions, 38 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 4ae3005bb0b3..a3e2a0add984 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -191,6 +191,47 @@ static Symbol getName(const AttrName & name, EvalState & state, Env & env)
 }
 
 
+static bool gcInitialised = false;
+
+void initGC()
+{
+    if (gcInitialised) return;
+
+#if HAVE_BOEHMGC
+    /* Initialise the Boehm garbage collector. */
+    GC_INIT();
+
+    GC_oom_fn = oomHandler;
+
+    /* Set the initial heap size to something fairly big (25% of
+       physical RAM, up to a maximum of 384 MiB) so that in most cases
+       we don't need to garbage collect at all.  (Collection has a
+       fairly significant overhead.)  The heap size can be overridden
+       through libgc's GC_INITIAL_HEAP_SIZE environment variable.  We
+       should probably also provide a nix.conf setting for this.  Note
+       that GC_expand_hp() causes a lot of virtual, but not physical
+       (resident) memory to be allocated.  This might be a problem on
+       systems that don't overcommit. */
+    if (!getenv("GC_INITIAL_HEAP_SIZE")) {
+        size_t size = 32 * 1024 * 1024;
+#if HAVE_SYSCONF && defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES)
+        size_t maxSize = 384 * 1024 * 1024;
+        long pageSize = sysconf(_SC_PAGESIZE);
+        long pages = sysconf(_SC_PHYS_PAGES);
+        if (pageSize != -1)
+            size = (pageSize * pages) / 4; // 25% of RAM
+        if (size > maxSize) size = maxSize;
+#endif
+        debug(format("setting initial heap size to %1% bytes") % size);
+        GC_expand_hp(size);
+    }
+
+#endif
+
+    gcInitialised = true;
+}
+
+
 EvalState::EvalState(const Strings & _searchPath)
     : sWith(symbols.create("<with>"))
     , sOutPath(symbols.create("outPath"))
@@ -220,44 +261,7 @@ EvalState::EvalState(const Strings & _searchPath)
 
     restricted = settings.get("restrict-eval", false);
 
-#if HAVE_BOEHMGC
-    static bool gcInitialised = false;
-    if (!gcInitialised) {
-
-        /* Initialise the Boehm garbage collector.  This isn't
-           necessary on most platforms, but for portability we do it
-           anyway. */
-        GC_INIT();
-
-        GC_oom_fn = oomHandler;
-
-        /* Set the initial heap size to something fairly big (25% of
-           physical RAM, up to a maximum of 384 MiB) so that in most
-           cases we don't need to garbage collect at all.  (Collection
-           has a fairly significant overhead.)  The heap size can be
-           overridden through libgc's GC_INITIAL_HEAP_SIZE environment
-           variable.  We should probably also provide a nix.conf
-           setting for this.  Note that GC_expand_hp() causes a lot of
-           virtual, but not physical (resident) memory to be
-           allocated.  This might be a problem on systems that don't
-           overcommit. */
-        if (!getenv("GC_INITIAL_HEAP_SIZE")) {
-            size_t size = 32 * 1024 * 1024;
-#if HAVE_SYSCONF && defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES)
-            size_t maxSize = 384 * 1024 * 1024;
-            long pageSize = sysconf(_SC_PAGESIZE);
-            long pages = sysconf(_SC_PHYS_PAGES);
-            if (pageSize != -1)
-                size = (pageSize * pages) / 4; // 25% of RAM
-            if (size > maxSize) size = maxSize;
-#endif
-            debug(format("setting initial heap size to %1% bytes") % size);
-            GC_expand_hp(size);
-        }
-
-        gcInitialised = true;
-    }
-#endif
+    assert(gcInitialised);
 
     /* Initialise the Nix expression search path. */
     Strings paths = tokenizeString<Strings>(getEnv("NIX_PATH", ""), ":");
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index bfaa4081d488..627fae3ff363 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -121,6 +121,10 @@ std::ostream & operator << (std::ostream & str, const Value & v);
 typedef list<std::pair<string, Path> > SearchPath;
 
 
+/* Initialise the Boehm GC, if applicable. */
+void initGC();
+
+
 class EvalState
 {
 public:
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index f3c8d3ba8953..10b95dad168c 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -1337,6 +1337,7 @@ int main(int argc, char * * argv)
 {
     return handleExceptions(argv[0], [&]() {
         initNix();
+        initGC();
 
         Strings opFlags, opArgs, searchPath;
         std::map<string, string> autoArgs_;
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index e7214e657bd5..5abaa617d245 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -93,6 +93,7 @@ int main(int argc, char * * argv)
 {
     return handleExceptions(argv[0], [&]() {
         initNix();
+        initGC();
 
         Strings files, searchPath;
         bool readStdin = false;