diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/attr-set.cc | 16 | ||||
-rw-r--r-- | src/libexpr/eval-inline.hh | 14 | ||||
-rw-r--r-- | src/libexpr/eval.cc | 72 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 9 | ||||
-rw-r--r-- | src/libstore/build.cc | 12 | ||||
-rw-r--r-- | src/libstore/derivations.cc | 2 | ||||
-rw-r--r-- | src/libstore/gc.cc | 4 | ||||
-rw-r--r-- | src/libstore/optimise-store.cc | 3 | ||||
-rwxr-xr-x | src/nix-build/nix-build.cc | 28 | ||||
-rw-r--r-- | src/nix-instantiate/nix-instantiate.cc | 20 | ||||
-rw-r--r-- | src/nix-prefetch-url/nix-prefetch-url.cc | 28 | ||||
-rw-r--r-- | src/nix/installables.cc | 24 | ||||
-rw-r--r-- | src/nix/repl.cc | 4 | ||||
-rw-r--r-- | src/nix/upgrade-nix.cc | 12 |
14 files changed, 132 insertions, 116 deletions
diff --git a/src/libexpr/attr-set.cc b/src/libexpr/attr-set.cc index 0474865c6d7d..0785897d2513 100644 --- a/src/libexpr/attr-set.cc +++ b/src/libexpr/attr-set.cc @@ -1,5 +1,5 @@ #include "attr-set.hh" -#include "eval.hh" +#include "eval-inline.hh" #include <algorithm> @@ -7,20 +7,6 @@ namespace nix { -/* Note: Various places expect the allocated memory to be zeroed. */ -static void * allocBytes(size_t n) -{ - void * p; -#if HAVE_BOEHMGC - p = GC_malloc(n); -#else - p = calloc(n, 1); -#endif - if (!p) throw std::bad_alloc(); - return p; -} - - /* Allocate a new array of attributes for an attribute set with a specific capacity. The space is implicitly reserved after the Bindings structure. */ diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index 8cc50e561354..c27116e3b448 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -78,4 +78,18 @@ inline void EvalState::forceList(Value & v, const Pos & pos) throwTypeError("value is %1% while a list was expected, at %2%", v, pos); } +/* Note: Various places expect the allocated memory to be zeroed. */ +inline void * allocBytes(size_t n) +{ + void * p; +#if HAVE_BOEHMGC + p = GC_MALLOC(n); +#else + p = calloc(n, 1); +#endif + if (!p) throw std::bad_alloc(); + return p; +} + + } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 517952164a97..e09297546c95 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -13,17 +13,14 @@ #include <sys/time.h> #include <sys/resource.h> +#include <sys/time.h> +#include <sys/resource.h> + #if HAVE_BOEHMGC #include <gc/gc.h> #include <gc/gc_cpp.h> -#define NEW new (UseGC) - -#else - -#define NEW new - #endif @@ -34,7 +31,7 @@ static char * dupString(const char * s) { char * t; #if HAVE_BOEHMGC - t = GC_strdup(s); + t = GC_STRDUP(s); #else t = strdup(s); #endif @@ -43,20 +40,6 @@ static char * dupString(const char * s) } -/* Note: Various places expect the allocated memory to be zeroed. */ -static void * allocBytes(size_t n) -{ - void * p; -#if HAVE_BOEHMGC - p = GC_malloc(n); -#else - p = calloc(n, 1); -#endif - if (!p) throw std::bad_alloc(); - return p; -} - - static void printValue(std::ostream & str, std::set<const Value *> & active, const Value & v) { checkInterrupt(); @@ -199,8 +182,15 @@ void initGC() #if HAVE_BOEHMGC /* Initialise the Boehm garbage collector. */ + + /* Don't look for interior pointers. This reduces the odds of + misdetection a bit. */ GC_set_all_interior_pointers(0); + /* We don't have any roots in data segments, so don't scan from + there. */ + GC_set_no_dls(1); + GC_INIT(); GC_set_oom_fn(oomHandler); @@ -346,7 +336,6 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store) EvalState::~EvalState() { - fileEvalCache.clear(); } @@ -451,7 +440,7 @@ Value * EvalState::addPrimOp(const string & name, string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; Symbol sym = symbols.create(name2); v->type = tPrimOp; - v->primOp = NEW PrimOp(primOp, arity, sym); + v->primOp = new PrimOp(primOp, arity, sym); staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; baseEnv.values[baseEnvDispl++] = v; baseEnv.values[0]->attrs->push_back(Attr(sym, v)); @@ -589,10 +578,19 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval) } +std::atomic<uint64_t> nrValuesFreed{0}; + +void finalizeValue(void * obj, void * data) +{ + nrValuesFreed++; +} + Value * EvalState::allocValue() { nrValues++; - return (Value *) allocBytes(sizeof(Value)); + auto v = (Value *) allocBytes(sizeof(Value)); + //GC_register_finalizer_no_order(v, finalizeValue, nullptr, nullptr, nullptr); + return v; } @@ -725,7 +723,17 @@ void EvalState::evalFile(const Path & path_, Value & v) } printTalkative("evaluating file '%1%'", path2); - Expr * e = parseExprFromFile(checkSourcePath(path2)); + Expr * e = nullptr; + + auto j = fileParseCache.find(path2); + if (j != fileParseCache.end()) + e = j->second; + + if (!e) + e = parseExprFromFile(checkSourcePath(path2)); + + fileParseCache[path2] = e; + try { eval(e, v); } catch (Error & e) { @@ -1712,6 +1720,20 @@ bool EvalState::eqValues(Value & v1, Value & v2) } +void EvalState::printStats2() +{ + struct rusage ru; + getrusage(RUSAGE_SELF, &ru); + + GC_prof_stats_s gc; + GC_get_prof_stats(&gc, sizeof(gc)); + + printError("STATS %d %d %d %d %d %d", + nrValues, nrValuesFreed.load(), nrValues - nrValuesFreed, + ru.ru_maxrss, + gc.heapsize_full, gc.free_bytes_full); +} + void EvalState::printStats() { bool showStats = getEnv("NIX_SHOW_STATS", "0") != "0"; diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 146f21255034..46bda86d084e 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -90,6 +90,14 @@ public: private: SrcToStore srcToStore; + /* A cache from path names to parse trees. */ +#if HAVE_BOEHMGC + typedef std::map<Path, Expr *, std::less<Path>, traceable_allocator<std::pair<const Path, Expr *> > > FileParseCache; +#else + typedef std::map<Path, Expr *> FileParseCache; +#endif + FileParseCache fileParseCache; + /* A cache from path names to values. */ #if HAVE_BOEHMGC typedef std::map<Path, Value, std::less<Path>, traceable_allocator<std::pair<const Path, Value> > > FileEvalCache; @@ -268,6 +276,7 @@ public: /* Print statistics. */ void printStats(); + void printStats2(); void realiseContext(const PathSet & context); diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 8eb19205970d..d75ca0be86ef 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -29,7 +29,9 @@ #include <sys/utsname.h> #include <sys/select.h> #include <sys/resource.h> +#include <sys/socket.h> #include <fcntl.h> +#include <netdb.h> #include <unistd.h> #include <errno.h> #include <cstring> @@ -1777,12 +1779,14 @@ static std::once_flag dns_resolve_flag; static void preloadNSS() { /* builtin:fetchurl can trigger a DNS lookup, which with glibc can trigger a dynamic library load of one of the glibc NSS libraries in a sandboxed child, which will fail unless the library's already - been loaded in the parent. So we force a download of an invalid URL to force the NSS machinery to + been loaded in the parent. So we force a lookup of an invalid domain to force the NSS machinery to load its lookup libraries in the parent before any child gets a chance to. */ std::call_once(dns_resolve_flag, []() { - DownloadRequest request("http://this.pre-initializes.the.dns.resolvers.invalid"); - request.tries = 1; // We only need to do it once, and this also suppresses an annoying warning - try { getDownloader()->download(request); } catch (...) {} + struct addrinfo *res = NULL; + + if (getaddrinfo("this.pre-initializes.the.dns.resolvers.invalid.", "http", NULL, &res) != 0) { + if (res) freeaddrinfo(res); + } }); } diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 74b861281ee0..1e187ec5e954 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -342,7 +342,7 @@ Hash hashDerivationModulo(Store & store, Derivation drv) Hash h = drvHashes[i.first]; if (!h) { assert(store.isValidPath(i.first)); - Derivation drv2 = readDerivation(i.first); + Derivation drv2 = readDerivation(store.toRealPath(i.first)); h = hashDerivationModulo(store, drv2); drvHashes[i.first] = h; } diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 40b4f965f253..b415d5421476 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -7,6 +7,7 @@ #include <queue> #include <algorithm> #include <regex> +#include <random> #include <sys/types.h> #include <sys/stat.h> @@ -832,7 +833,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) alphabetically first (e.g. /nix/store/000...). This matters when using --max-freed etc. */ vector<Path> entries_(entries.begin(), entries.end()); - random_shuffle(entries_.begin(), entries_.end()); + std::mt19937 gen(1); + std::shuffle(entries_.begin(), entries_.end(), gen); for (auto & i : entries_) tryToDelete(state, i); diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 7840167d7772..991512f21795 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -104,8 +104,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, *.app/Contents/Resources/\*.lproj seem to be the only paths affected. See https://github.com/NixOS/nix/issues/1443 for more discussion. */ - if (std::regex_search(path, std::regex("\\.app/Contents/PkgInfo$")) || - std::regex_search(path, std::regex("\\.app/Contents/Resources/.+\\.lproj$"))) + if (std::regex_search(path, std::regex("\\.app/Contents/.+$"))) { debug(format("'%1%' is not allowed to be linked in macOS") % path); return; diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 21d99878a518..de0e9118fd21 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -239,10 +239,10 @@ void mainWrapped(int argc, char * * argv) auto store = openStore(); - EvalState state(myArgs.searchPath, store); - state.repair = repair; + auto state = std::make_unique<EvalState>(myArgs.searchPath, store); + state->repair = repair; - Bindings & autoArgs = *myArgs.getAutoArgs(state); + Bindings & autoArgs = *myArgs.getAutoArgs(*state); if (packages) { std::ostringstream joined; @@ -268,7 +268,7 @@ void mainWrapped(int argc, char * * argv) std::vector<Expr *> exprs; if (readStdin) - exprs = {state.parseStdin()}; + exprs = {state->parseStdin()}; else for (auto i : left) { auto absolute = i; @@ -276,13 +276,13 @@ void mainWrapped(int argc, char * * argv) absolute = canonPath(absPath(i), true); } catch (Error e) {}; if (fromArgs) - exprs.push_back(state.parseExprFromString(i, absPath("."))); + exprs.push_back(state->parseExprFromString(i, absPath("."))); else if (store->isStorePath(absolute) && std::regex_match(absolute, std::regex(".*\\.drv(!.*)?"))) - drvs.push_back(DrvInfo(state, store, absolute)); + drvs.push_back(DrvInfo(*state, store, absolute)); else /* If we're in a #! script, interpret filenames relative to the script. */ - exprs.push_back(state.parseExprFromFile(resolveExprPath(state.checkSourcePath(lookupFileArg(state, + exprs.push_back(state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state, inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i))))); } @@ -291,12 +291,12 @@ void mainWrapped(int argc, char * * argv) for (auto e : exprs) { Value vRoot; - state.eval(e, vRoot); + state->eval(e, vRoot); for (auto & i : attrPaths) { - Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot)); - state.forceValue(v); - getDerivations(state, v, "", autoArgs, drvs, false); + Value & v(*findAlongAttrPath(*state, i, autoArgs, vRoot)); + state->forceValue(v); + getDerivations(*state, v, "", autoArgs, drvs, false); } } @@ -332,12 +332,12 @@ void mainWrapped(int argc, char * * argv) if (shell == "") { try { - auto expr = state.parseExprFromString("(import <nixpkgs> {}).bashInteractive", absPath(".")); + auto expr = state->parseExprFromString("(import <nixpkgs> {}).bashInteractive", absPath(".")); Value v; - state.eval(expr, v); + state->eval(expr, v); - auto drv = getDerivation(state, v, false); + auto drv = getDerivation(*state, v, false); if (!drv) throw Error("the 'bashInteractive' attribute in <nixpkgs> did not evaluate to a derivation"); diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index 5049460c7544..eb6d34dd8219 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -158,16 +158,16 @@ int main(int argc, char * * argv) auto store = openStore(); - EvalState state(myArgs.searchPath, store); - state.repair = repair; + auto state = std::make_unique<EvalState>(myArgs.searchPath, store); + state->repair = repair; - Bindings & autoArgs = *myArgs.getAutoArgs(state); + Bindings & autoArgs = *myArgs.getAutoArgs(*state); if (attrPaths.empty()) attrPaths = {""}; if (findFile) { for (auto & i : files) { - Path p = state.findFile(i); + Path p = state->findFile(i); if (p == "") throw Error(format("unable to find '%1%'") % i); std::cout << p << std::endl; } @@ -175,20 +175,20 @@ int main(int argc, char * * argv) } if (readStdin) { - Expr * e = state.parseStdin(); - processExpr(state, attrPaths, parseOnly, strict, autoArgs, + Expr * e = state->parseStdin(); + processExpr(*state, attrPaths, parseOnly, strict, autoArgs, evalOnly, outputKind, xmlOutputSourceLocation, e); } else if (files.empty() && !fromArgs) files.push_back("./default.nix"); for (auto & i : files) { Expr * e = fromArgs - ? state.parseExprFromString(i, absPath(".")) - : state.parseExprFromFile(resolveExprPath(state.checkSourcePath(lookupFileArg(state, i)))); - processExpr(state, attrPaths, parseOnly, strict, autoArgs, + ? state->parseExprFromString(i, absPath(".")) + : state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state, i)))); + processExpr(*state, attrPaths, parseOnly, strict, autoArgs, evalOnly, outputKind, xmlOutputSourceLocation, e); } - state.printStats(); + state->printStats(); }); } diff --git a/src/nix-prefetch-url/nix-prefetch-url.cc b/src/nix-prefetch-url/nix-prefetch-url.cc index fa7ee254500c..50b2c2803ec9 100644 --- a/src/nix-prefetch-url/nix-prefetch-url.cc +++ b/src/nix-prefetch-url/nix-prefetch-url.cc @@ -95,9 +95,9 @@ int main(int argc, char * * argv) throw UsageError("too many arguments"); auto store = openStore(); - EvalState state(myArgs.searchPath, store); + auto state = std::make_unique<EvalState>(myArgs.searchPath, store); - Bindings & autoArgs = *myArgs.getAutoArgs(state); + Bindings & autoArgs = *myArgs.getAutoArgs(*state); /* If -A is given, get the URI from the specified Nix expression. */ @@ -107,33 +107,33 @@ int main(int argc, char * * argv) throw UsageError("you must specify a URI"); uri = args[0]; } else { - Path path = resolveExprPath(lookupFileArg(state, args.empty() ? "." : args[0])); + Path path = resolveExprPath(lookupFileArg(*state, args.empty() ? "." : args[0])); Value vRoot; - state.evalFile(path, vRoot); - Value & v(*findAlongAttrPath(state, attrPath, autoArgs, vRoot)); - state.forceAttrs(v); + state->evalFile(path, vRoot); + Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot)); + state->forceAttrs(v); /* Extract the URI. */ - auto attr = v.attrs->find(state.symbols.create("urls")); + auto attr = v.attrs->find(state->symbols.create("urls")); if (attr == v.attrs->end()) throw Error("attribute set does not contain a 'urls' attribute"); - state.forceList(*attr->value); + state->forceList(*attr->value); if (attr->value->listSize() < 1) throw Error("'urls' list is empty"); - uri = state.forceString(*attr->value->listElems()[0]); + uri = state->forceString(*attr->value->listElems()[0]); /* Extract the hash mode. */ - attr = v.attrs->find(state.symbols.create("outputHashMode")); + attr = v.attrs->find(state->symbols.create("outputHashMode")); if (attr == v.attrs->end()) printInfo("warning: this does not look like a fetchurl call"); else - unpack = state.forceString(*attr->value) == "recursive"; + unpack = state->forceString(*attr->value) == "recursive"; /* Extract the name. */ if (name.empty()) { - attr = v.attrs->find(state.symbols.create("name")); + attr = v.attrs->find(state->symbols.create("name")); if (attr != v.attrs->end()) - name = state.forceString(*attr->value); + name = state->forceString(*attr->value); } } @@ -158,7 +158,7 @@ int main(int argc, char * * argv) if (storePath.empty()) { - auto actualUri = resolveMirrorUri(state, uri); + auto actualUri = resolveMirrorUri(*state, uri); /* Download the file. */ DownloadRequest req(actualUri); diff --git a/src/nix/installables.cc b/src/nix/installables.cc index a3fdd8a2808d..0be992b03c5a 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -86,22 +86,6 @@ Buildable Installable::toBuildable() return std::move(buildables[0]); } -struct InstallableStoreDrv : Installable -{ - Path drvPath; - - InstallableStoreDrv(const Path & drvPath) : drvPath(drvPath) { } - - std::string what() override { return drvPath; } - - Buildables toBuildables() override - { - Buildable b = {drvPath}; - // FIXME: add outputs? - return {b}; - } -}; - struct InstallableStorePath : Installable { Path storePath; @@ -226,12 +210,8 @@ static std::vector<std::shared_ptr<Installable>> parseInstallables( auto path = store->toStorePath(store->followLinksToStore(s)); - if (store->isStorePath(path)) { - if (isDerivation(path)) - result.push_back(std::make_shared<InstallableStoreDrv>(path)); - else - result.push_back(std::make_shared<InstallableStorePath>(path)); - } + if (store->isStorePath(path)) + result.push_back(std::make_shared<InstallableStorePath>(path)); } else if (s == "" || std::regex_match(s, attrPathRegex)) diff --git a/src/nix/repl.cc b/src/nix/repl.cc index f84774a53367..4723a1974b77 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -693,8 +693,8 @@ struct CmdRepl : StoreCommand, MixEvalArgs void run(ref<Store> store) override { - NixRepl repl(searchPath, openStore()); - repl.mainLoop(files); + auto repl = std::make_unique<NixRepl>(searchPath, openStore()); + repl->mainLoop(files); } }; diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 21892c31a893..e23ae792369c 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -118,13 +118,13 @@ struct CmdUpgradeNix : StoreCommand auto req = DownloadRequest("https://github.com/NixOS/nixpkgs/raw/master/nixos/modules/installer/tools/nix-fallback-paths.nix"); auto res = getDownloader()->download(req); - EvalState state(Strings(), store); - auto v = state.allocValue(); - state.eval(state.parseExprFromString(*res.data, "/no-such-path"), *v); - Bindings & bindings(*state.allocBindings(0)); - auto v2 = findAlongAttrPath(state, settings.thisSystem, bindings, *v); + auto state = std::make_unique<EvalState>(Strings(), store); + auto v = state->allocValue(); + state->eval(state->parseExprFromString(*res.data, "/no-such-path"), *v); + Bindings & bindings(*state->allocBindings(0)); + auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v); - return state.forceString(*v2); + return state->forceString(*v2); } }; |