From 726f7f7fc92f4914bca450a37b8b85b1018afc01 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 19 Mar 2015 20:02:37 +0100 Subject: [PATCH] Fix Boehm API violation We were calling GC_INIT() after doing an allocation (in the baseEnv construction), which is not allowed. --- src/libexpr/eval.cc | 80 ++++++++++++++------------ src/libexpr/eval.hh | 4 ++ src/nix-env/nix-env.cc | 1 + src/nix-instantiate/nix-instantiate.cc | 1 + 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 4ae3005bb..a3e2a0add 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("")) , 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(getEnv("NIX_PATH", ""), ":"); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index bfaa4081d..627fae3ff 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 > 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 f3c8d3ba8..10b95dad1 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 autoArgs_; diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index e7214e657..5abaa617d 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;