Fix --timeout
I'm not sure if it has ever worked correctly. The line "lastWait = after;" seems to mean that the timer was reset every time a build produced log output. Note that the timeout is now per build, as documented ("the maximum number of seconds that a builder can run").
This commit is contained in:
parent
f9974f856e
commit
772b70952f
1 changed files with 25 additions and 38 deletions
|
@ -186,9 +186,10 @@ struct Child
|
||||||
{
|
{
|
||||||
WeakGoalPtr goal;
|
WeakGoalPtr goal;
|
||||||
set<int> fds;
|
set<int> fds;
|
||||||
bool monitorForSilence;
|
bool respectTimeouts;
|
||||||
bool inBuildSlot;
|
bool inBuildSlot;
|
||||||
time_t lastOutput; /* time we last got output on stdout/stderr */
|
time_t lastOutput; /* time we last got output on stdout/stderr */
|
||||||
|
time_t timeStarted;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef map<pid_t, Child> Children;
|
typedef map<pid_t, Child> Children;
|
||||||
|
@ -232,9 +233,6 @@ private:
|
||||||
/* Last time the goals in `waitingForAWhile' where woken up. */
|
/* Last time the goals in `waitingForAWhile' where woken up. */
|
||||||
time_t lastWokenUp;
|
time_t lastWokenUp;
|
||||||
|
|
||||||
/* Last time `waitForInput' was last called. */
|
|
||||||
time_t lastWait;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* Set if at least one derivation had a BuildError (i.e. permanent
|
/* Set if at least one derivation had a BuildError (i.e. permanent
|
||||||
|
@ -266,7 +264,7 @@ public:
|
||||||
/* Registers a running child process. `inBuildSlot' means that
|
/* Registers a running child process. `inBuildSlot' means that
|
||||||
the process counts towards the jobs limit. */
|
the process counts towards the jobs limit. */
|
||||||
void childStarted(GoalPtr goal, pid_t pid,
|
void childStarted(GoalPtr goal, pid_t pid,
|
||||||
const set<int> & fds, bool inBuildSlot, bool monitorForSilence);
|
const set<int> & fds, bool inBuildSlot, bool respectTimeouts);
|
||||||
|
|
||||||
/* Unregisters a running child process. `wakeSleepers' should be
|
/* Unregisters a running child process. `wakeSleepers' should be
|
||||||
false if there is no sense in waking up goals that are sleeping
|
false if there is no sense in waking up goals that are sleeping
|
||||||
|
@ -2994,14 +2992,14 @@ unsigned Worker::getNrLocalBuilds()
|
||||||
|
|
||||||
void Worker::childStarted(GoalPtr goal,
|
void Worker::childStarted(GoalPtr goal,
|
||||||
pid_t pid, const set<int> & fds, bool inBuildSlot,
|
pid_t pid, const set<int> & fds, bool inBuildSlot,
|
||||||
bool monitorForSilence)
|
bool respectTimeouts)
|
||||||
{
|
{
|
||||||
Child child;
|
Child child;
|
||||||
child.goal = goal;
|
child.goal = goal;
|
||||||
child.fds = fds;
|
child.fds = fds;
|
||||||
child.lastOutput = time(0);
|
child.timeStarted = child.lastOutput = time(0);
|
||||||
child.inBuildSlot = inBuildSlot;
|
child.inBuildSlot = inBuildSlot;
|
||||||
child.monitorForSilence = monitorForSilence;
|
child.respectTimeouts = respectTimeouts;
|
||||||
children[pid] = child;
|
children[pid] = child;
|
||||||
if (inBuildSlot) nrLocalBuilds++;
|
if (inBuildSlot) nrLocalBuilds++;
|
||||||
}
|
}
|
||||||
|
@ -3117,32 +3115,23 @@ void Worker::waitForInput()
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
time_t before = time(0);
|
time_t before = time(0);
|
||||||
|
|
||||||
/* If a global timeout has been set, sleep until it's done. */
|
/* If we're monitoring for silence on stdout/stderr, or if there
|
||||||
if (settings.buildTimeout != 0) {
|
is a build timeout, then wait for input until the first
|
||||||
useTimeout = true;
|
deadline for any child. */
|
||||||
if (lastWait == 0 || lastWait > before) lastWait = before;
|
assert(sizeof(time_t) >= sizeof(long));
|
||||||
timeout.tv_sec = std::max((time_t) 0, lastWait + settings.buildTimeout - before);
|
time_t nearest = LONG_MAX; // nearest deadline
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're monitoring for silence on stdout/stderr, sleep until
|
|
||||||
the first deadline for any child. */
|
|
||||||
if (settings.maxSilentTime != 0) {
|
|
||||||
time_t oldest = 0;
|
|
||||||
foreach (Children::iterator, i, children) {
|
foreach (Children::iterator, i, children) {
|
||||||
if (i->second.monitorForSilence) {
|
if (!i->second.respectTimeouts) continue;
|
||||||
oldest = oldest == 0 || i->second.lastOutput < oldest
|
if (settings.maxSilentTime != 0)
|
||||||
? i->second.lastOutput : oldest;
|
nearest = std::min(nearest, i->second.lastOutput + settings.maxSilentTime);
|
||||||
|
if (settings.buildTimeout != 0)
|
||||||
|
nearest = std::min(nearest, i->second.timeStarted + settings.buildTimeout);
|
||||||
}
|
}
|
||||||
}
|
if (nearest != LONG_MAX) {
|
||||||
if (oldest) {
|
timeout.tv_sec = std::max((time_t) 1, nearest - before);
|
||||||
time_t silenceTimeout = std::max((time_t) 0, oldest + settings.maxSilentTime - before);
|
|
||||||
timeout.tv_sec = useTimeout
|
|
||||||
? std::min(silenceTimeout, timeout.tv_sec)
|
|
||||||
: silenceTimeout;
|
|
||||||
useTimeout = true;
|
useTimeout = true;
|
||||||
printMsg(lvlVomit, format("sleeping %1% seconds") % timeout.tv_sec);
|
printMsg(lvlVomit, format("sleeping %1% seconds") % timeout.tv_sec);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* If we are polling goals that are waiting for a lock, then wake
|
/* If we are polling goals that are waiting for a lock, then wake
|
||||||
up after a few seconds at most. */
|
up after a few seconds at most. */
|
||||||
|
@ -3151,7 +3140,7 @@ void Worker::waitForInput()
|
||||||
if (lastWokenUp == 0)
|
if (lastWokenUp == 0)
|
||||||
printMsg(lvlError, "waiting for locks or build slots...");
|
printMsg(lvlError, "waiting for locks or build slots...");
|
||||||
if (lastWokenUp == 0 || lastWokenUp > before) lastWokenUp = before;
|
if (lastWokenUp == 0 || lastWokenUp > before) lastWokenUp = before;
|
||||||
timeout.tv_sec = std::max((time_t) 0, (time_t) (lastWokenUp + settings.pollInterval - before));
|
timeout.tv_sec = std::max((time_t) 1, (time_t) (lastWokenUp + settings.pollInterval - before));
|
||||||
} else lastWokenUp = 0;
|
} else lastWokenUp = 0;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -3175,9 +3164,6 @@ void Worker::waitForInput()
|
||||||
|
|
||||||
time_t after = time(0);
|
time_t after = time(0);
|
||||||
|
|
||||||
/* Keep track of when we were last called. */
|
|
||||||
lastWait = after;
|
|
||||||
|
|
||||||
/* Process all available file descriptors. */
|
/* Process all available file descriptors. */
|
||||||
|
|
||||||
/* Since goals may be canceled from inside the loop below (causing
|
/* Since goals may be canceled from inside the loop below (causing
|
||||||
|
@ -3218,7 +3204,7 @@ void Worker::waitForInput()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.maxSilentTime != 0 &&
|
if (settings.maxSilentTime != 0 &&
|
||||||
j->second.monitorForSilence &&
|
j->second.respectTimeouts &&
|
||||||
after - j->second.lastOutput >= (time_t) settings.maxSilentTime)
|
after - j->second.lastOutput >= (time_t) settings.maxSilentTime)
|
||||||
{
|
{
|
||||||
printMsg(lvlError,
|
printMsg(lvlError,
|
||||||
|
@ -3228,7 +3214,8 @@ void Worker::waitForInput()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.buildTimeout != 0 &&
|
if (settings.buildTimeout != 0 &&
|
||||||
after - before >= (time_t) settings.buildTimeout)
|
j->second.respectTimeouts &&
|
||||||
|
after - j->second.timeStarted >= (time_t) settings.buildTimeout)
|
||||||
{
|
{
|
||||||
printMsg(lvlError,
|
printMsg(lvlError,
|
||||||
format("%1% timed out after %2% seconds")
|
format("%1% timed out after %2% seconds")
|
||||||
|
|
Loading…
Reference in a new issue