about summary refs log tree commit diff
path: root/src/libstore/build.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/build.cc')
-rw-r--r--src/libstore/build.cc103
1 files changed, 59 insertions, 44 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index ed4e0f659da3..ba3f3a371d8c 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -22,6 +22,7 @@
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <sys/select.h>
+#include <sys/resource.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
@@ -239,6 +240,9 @@ private:
     /* Last time the goals in `waitingForAWhile' where woken up. */
     time_t lastWokenUp;
 
+    /* Cache for pathContentsGood(). */
+    std::map<Path, bool> pathContentsGoodCache;
+
 public:
 
     /* Set if at least one derivation had a BuildError (i.e. permanent
@@ -304,6 +308,12 @@ public:
     void waitForInput();
 
     unsigned int exitStatus();
+
+    /* Check whether the given valid path exists and has the right
+       contents. */
+    bool pathContentsGood(const Path & path);
+
+    void markContentsGood(const Path & path);
 };
 
 
@@ -1038,11 +1048,6 @@ void DerivationGoal::haveDerivation()
         return;
     }
 
-    /* Check whether any output previously failed to build.  If so,
-       don't bother. */
-    for (auto & i : invalidOutputs)
-        if (pathFailed(i)) return;
-
     /* Reject doing a hash build of anything other than a fixed-output
        derivation. */
     if (buildMode == bmHash) {
@@ -1159,7 +1164,7 @@ void DerivationGoal::repairClosure()
     /* Check each path (slow!). */
     PathSet broken;
     for (auto & i : outputClosure) {
-        if (worker.store.pathContentsGood(i)) continue;
+        if (worker.pathContentsGood(i)) continue;
         printMsg(lvlError, format("found corrupted or missing path ‘%1%’ in the output closure of ‘%2%’") % i % drvPath);
         Path drvPath2 = outputsToDrv[i];
         if (drvPath2 == "")
@@ -1313,12 +1318,6 @@ void DerivationGoal::tryToBuild()
         deletePath(path);
     }
 
-    /* Check again whether any output previously failed to build,
-       because some other process may have tried and failed before we
-       acquired the lock. */
-    for (auto & i : drv->outputs)
-        if (pathFailed(i.second.path)) return;
-
     /* Don't do a remote build if the derivation has the attribute
        `preferLocalBuild' set.  Also, check and repair modes are only
        supported for local builds. */
@@ -1540,17 +1539,6 @@ void DerivationGoal::buildDone()
                 statusOk(status) ? BuildResult::OutputRejected :
                 fixedOutput || diskFull ? BuildResult::TransientFailure :
                 BuildResult::PermanentFailure;
-
-            /* Register the outputs of this build as "failed" so we
-               won't try to build them again (negative caching).
-               However, don't do this for fixed-output derivations,
-               since they're likely to fail for transient reasons
-               (e.g., fetchurl not being able to access the network).
-               Hook errors (like communication problems with the
-               remote machine) shouldn't be cached either. */
-            if (settings.cacheFailure && !fixedOutput && !diskFull)
-                for (auto & i : drv->outputs)
-                    worker.store.registerFailedPath(i.second.path);
         }
 
         done(st, e.msg());
@@ -2386,6 +2374,12 @@ void DerivationGoal::runChild()
         if (cur != -1) personality(cur | ADDR_NO_RANDOMIZE);
 #endif
 
+        /* Disable core dumps by default. */
+        struct rlimit limit = { 0, RLIM_INFINITY };
+        setrlimit(RLIMIT_CORE, &limit);
+
+        // FIXME: set other limits to deterministic values?
+
         /* Fill in the environment. */
         Strings envStrs;
         for (auto & i : env)
@@ -2743,6 +2737,15 @@ void DerivationGoal::registerOutputs()
                     throw Error(format("derivation ‘%1%’ may not be deterministic: output ‘%2%’ differs")
                         % drvPath % path);
             }
+
+            /* Since we verified the build, it's now ultimately
+               trusted. */
+            if (!info.ultimate) {
+                info.ultimate = true;
+                worker.store.signPathInfo(info);
+                worker.store.registerValidPaths({info});
+            }
+
             continue;
         }
 
@@ -2790,7 +2793,7 @@ void DerivationGoal::registerOutputs()
         if (curRound == nrRounds) {
             worker.store.optimisePath(path); // FIXME: combine with scanForReferences()
 
-            worker.store.markContentsGood(path);
+            worker.markContentsGood(path);
         }
 
         ValidPathInfo info;
@@ -2799,6 +2802,9 @@ void DerivationGoal::registerOutputs()
         info.narSize = hash.second;
         info.references = references;
         info.deriver = drvPath;
+        info.ultimate = true;
+        worker.store.signPathInfo(info);
+
         infos.push_back(info);
     }
 
@@ -2965,30 +2971,13 @@ PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash)
         if (!wantOutput(i.first, wantedOutputs)) continue;
         bool good =
             worker.store.isValidPath(i.second.path) &&
-            (!checkHash || worker.store.pathContentsGood(i.second.path));
+            (!checkHash || worker.pathContentsGood(i.second.path));
         if (good == returnValid) result.insert(i.second.path);
     }
     return result;
 }
 
 
-bool DerivationGoal::pathFailed(const Path & path)
-{
-    if (!settings.cacheFailure) return false;
-
-    if (!worker.store.hasPathFailed(path)) return false;
-
-    printMsg(lvlError, format("builder for ‘%1%’ failed previously (cached)") % path);
-
-    if (settings.printBuildTrace)
-        printMsg(lvlError, format("@ build-failed %1% - cached") % drvPath);
-
-    done(BuildResult::CachedFailure);
-
-    return true;
-}
-
-
 Path DerivationGoal::addHashRewrite(const Path & path)
 {
     string h1 = string(path, settings.nixStore.size() + 1, 32);
@@ -3010,7 +2999,7 @@ void DerivationGoal::done(BuildResult::Status status, const string & msg)
     amDone(result.success() ? ecSuccess : ecFailed);
     if (result.status == BuildResult::TimedOut)
         worker.timedOut = true;
-    if (result.status == BuildResult::PermanentFailure || result.status == BuildResult::CachedFailure)
+    if (result.status == BuildResult::PermanentFailure)
         worker.permanentFailure = true;
 }
 
@@ -3373,7 +3362,7 @@ void SubstitutionGoal::finished()
     outputLock->setDeletion(true);
     outputLock.reset();
 
-    worker.store.markContentsGood(storePath);
+    worker.markContentsGood(storePath);
 
     printMsg(lvlChatty,
         format("substitution of path ‘%1%’ succeeded") % storePath);
@@ -3773,6 +3762,32 @@ unsigned int Worker::exitStatus()
 }
 
 
+bool Worker::pathContentsGood(const Path & path)
+{
+    std::map<Path, bool>::iterator i = pathContentsGoodCache.find(path);
+    if (i != pathContentsGoodCache.end()) return i->second;
+    printMsg(lvlInfo, format("checking path ‘%1%’...") % path);
+    ValidPathInfo info = store.queryPathInfo(path);
+    bool res;
+    if (!pathExists(path))
+        res = false;
+    else {
+        HashResult current = hashPath(info.narHash.type, path);
+        Hash nullHash(htSHA256);
+        res = info.narHash == nullHash || info.narHash == current.first;
+    }
+    pathContentsGoodCache[path] = res;
+    if (!res) printMsg(lvlError, format("path ‘%1%’ is corrupted or missing!") % path);
+    return res;
+}
+
+
+void Worker::markContentsGood(const Path & path)
+{
+    pathContentsGoodCache[path] = true;
+}
+
+
 //////////////////////////////////////////////////////////////////////