about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2004-07-01T16·24+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-07-01T16·24+0000
commit056cd1d3b7778bbe177d74aea3aadca9e1a7be79 (patch)
tree882347aa7e3035172249b4c377019610be655a29
parent638ce339a52da893693f667c8b330a2adefdd92a (diff)
* Don't go into a (sometimes infinite) loop calling the build hook.
-rw-r--r--src/libstore/normalise.cc40
1 files changed, 24 insertions, 16 deletions
diff --git a/src/libstore/normalise.cc b/src/libstore/normalise.cc
index d91e5ea268ae..c392cfb2fb35 100644
--- a/src/libstore/normalise.cc
+++ b/src/libstore/normalise.cc
@@ -164,10 +164,10 @@ public:
     /* Registers / unregisters a running child process. */
     void childStarted(GoalPtr goal, pid_t pid, int fdOutput,
         bool inBuildSlot);
-    void childTerminated(pid_t pid);
+    void childTerminated(pid_t pid, bool wakeSleepers = true);
 
     /* Add a goal to the set of goals waiting for a build slot. */
-    void waitForBuildSlot(GoalPtr goal);
+    void waitForBuildSlot(GoalPtr goal, bool reallyWait = false);
     
     /* Loop until the specified top-level goal has finished.  Returns
        true if it has finished succesfully. */
@@ -225,7 +225,7 @@ void Goal::waiteeDone(GoalPtr waitee, bool success)
             goal->waiters = waiters2;
         }
         waitees.clear();
-        
+
         worker.wakeUp(shared_from_this());
     }
 }
@@ -553,7 +553,7 @@ void NormalisationGoal::tryToBuild()
                 return;
             case rpPostpone:
                 /* Not now; wait until at least one child finishes. */
-                worker.waitForBuildSlot(shared_from_this());
+                worker.waitForBuildSlot(shared_from_this(), true);
                 return;
             case rpDecline:
                 /* We should do it ourselves. */
@@ -813,7 +813,7 @@ void NormalisationGoal::terminateBuildHook()
     debug("terminating build hook");
     pid_t savedPid = pid;
     pid.wait(true);
-    worker.childTerminated(savedPid);
+    worker.childTerminated(savedPid, false);
     fromHook.readSide.close();
     toHook.writeSide.close();
     fdLogFile.close();
@@ -1821,7 +1821,7 @@ void Worker::childStarted(GoalPtr goal,
 }
 
 
-void Worker::childTerminated(pid_t pid)
+void Worker::childTerminated(pid_t pid, bool wakeSleepers)
 {
     Children::iterator i = children.find(pid);
     assert(i != children.end());
@@ -1833,21 +1833,29 @@ void Worker::childTerminated(pid_t pid)
 
     children.erase(pid);
 
-    /* Wake up goals waiting for a build slot. */
-    for (WeakGoals::iterator i = wantingToBuild.begin();
-         i != wantingToBuild.end(); ++i)
-    {
-        GoalPtr goal = i->lock();
-        if (goal) wakeUp(goal);
+    if (wakeSleepers) {
+        
+        /* Wake up goals waiting for a build slot. */
+        for (WeakGoals::iterator i = wantingToBuild.begin();
+             i != wantingToBuild.end(); ++i)
+        {
+            GoalPtr goal = i->lock();
+            if (goal) wakeUp(goal);
+        }
+
+        wantingToBuild.clear();
+        
     }
-    wantingToBuild.clear();
 }
 
 
-void Worker::waitForBuildSlot(GoalPtr goal)
+void Worker::waitForBuildSlot(GoalPtr goal, bool reallyWait)
 {
     debug("wait for build slot");
-    if (canBuildMore())
+    if (reallyWait && children.size() == 0)
+        throw Error("waiting for a build slot, yet there are no children - "
+            "maybe the build hook gave an inappropriate `postpone' reply?");
+    if (!reallyWait && canBuildMore())
         wakeUp(goal); /* we can do it right away */
     else
         wantingToBuild.insert(goal);
@@ -1981,7 +1989,7 @@ Path realiseStoreExpr(const Path & nePath)
 
     Worker worker;
     if (!worker.run(worker.makeRealisationGoal(nePath)))
-        throw Error(format("realisation of store expressions `%1%' failed") % nePath);
+        throw Error(format("realisation of store expression `%1%' failed") % nePath);
 
     return queryNormalForm(nePath);
 }