* Don't go into a (sometimes infinite) loop calling the build hook.

This commit is contained in:
Eelco Dolstra 2004-07-01 16:24:35 +00:00
parent 638ce339a5
commit 056cd1d3b7

View file

@ -164,10 +164,10 @@ public:
/* Registers / unregisters a running child process. */ /* Registers / unregisters a running child process. */
void childStarted(GoalPtr goal, pid_t pid, int fdOutput, void childStarted(GoalPtr goal, pid_t pid, int fdOutput,
bool inBuildSlot); 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. */ /* 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 /* Loop until the specified top-level goal has finished. Returns
true if it has finished succesfully. */ true if it has finished succesfully. */
@ -553,7 +553,7 @@ void NormalisationGoal::tryToBuild()
return; return;
case rpPostpone: case rpPostpone:
/* Not now; wait until at least one child finishes. */ /* Not now; wait until at least one child finishes. */
worker.waitForBuildSlot(shared_from_this()); worker.waitForBuildSlot(shared_from_this(), true);
return; return;
case rpDecline: case rpDecline:
/* We should do it ourselves. */ /* We should do it ourselves. */
@ -813,7 +813,7 @@ void NormalisationGoal::terminateBuildHook()
debug("terminating build hook"); debug("terminating build hook");
pid_t savedPid = pid; pid_t savedPid = pid;
pid.wait(true); pid.wait(true);
worker.childTerminated(savedPid); worker.childTerminated(savedPid, false);
fromHook.readSide.close(); fromHook.readSide.close();
toHook.writeSide.close(); toHook.writeSide.close();
fdLogFile.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); Children::iterator i = children.find(pid);
assert(i != children.end()); assert(i != children.end());
@ -1833,6 +1833,8 @@ void Worker::childTerminated(pid_t pid)
children.erase(pid); children.erase(pid);
if (wakeSleepers) {
/* Wake up goals waiting for a build slot. */ /* Wake up goals waiting for a build slot. */
for (WeakGoals::iterator i = wantingToBuild.begin(); for (WeakGoals::iterator i = wantingToBuild.begin();
i != wantingToBuild.end(); ++i) i != wantingToBuild.end(); ++i)
@ -1840,14 +1842,20 @@ void Worker::childTerminated(pid_t pid)
GoalPtr goal = i->lock(); GoalPtr goal = i->lock();
if (goal) wakeUp(goal); 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"); 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 */ wakeUp(goal); /* we can do it right away */
else else
wantingToBuild.insert(goal); wantingToBuild.insert(goal);
@ -1981,7 +1989,7 @@ Path realiseStoreExpr(const Path & nePath)
Worker worker; Worker worker;
if (!worker.run(worker.makeRealisationGoal(nePath))) 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); return queryNormalForm(nePath);
} }