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; | ||||
|     set<int> fds; | ||||
|     bool monitorForSilence; | ||||
|     bool respectTimeouts; | ||||
|     bool inBuildSlot; | ||||
|     time_t lastOutput; /* time we last got output on stdout/stderr */ | ||||
|     time_t timeStarted; | ||||
| }; | ||||
| 
 | ||||
| typedef map<pid_t, Child> Children; | ||||
|  | @ -232,9 +233,6 @@ private: | |||
|     /* Last time the goals in `waitingForAWhile' where woken up. */ | ||||
|     time_t lastWokenUp; | ||||
| 
 | ||||
|     /* Last time `waitForInput' was last called.  */ | ||||
|     time_t lastWait; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     /* 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
 | ||||
|        the process counts towards the jobs limit. */ | ||||
|     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
 | ||||
|        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, | ||||
|     pid_t pid, const set<int> & fds, bool inBuildSlot, | ||||
|     bool monitorForSilence) | ||||
|     bool respectTimeouts) | ||||
| { | ||||
|     Child child; | ||||
|     child.goal = goal; | ||||
|     child.fds = fds; | ||||
|     child.lastOutput = time(0); | ||||
|     child.timeStarted = child.lastOutput = time(0); | ||||
|     child.inBuildSlot = inBuildSlot; | ||||
|     child.monitorForSilence = monitorForSilence; | ||||
|     child.respectTimeouts = respectTimeouts; | ||||
|     children[pid] = child; | ||||
|     if (inBuildSlot) nrLocalBuilds++; | ||||
| } | ||||
|  | @ -3117,32 +3115,23 @@ void Worker::waitForInput() | |||
|     timeout.tv_usec = 0; | ||||
|     time_t before = time(0); | ||||
| 
 | ||||
|     /* If a global timeout has been set, sleep until it's done.  */ | ||||
|     if (settings.buildTimeout != 0) { | ||||
|         useTimeout = true; | ||||
|         if (lastWait == 0 || lastWait > before) lastWait = before; | ||||
|         timeout.tv_sec = std::max((time_t) 0, lastWait + settings.buildTimeout - before); | ||||
|     } | ||||
| 
 | ||||
|     /* 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; | ||||
|     /* If we're monitoring for silence on stdout/stderr, or if there
 | ||||
|        is a build timeout, then wait for input until the first | ||||
|        deadline for any child. */ | ||||
|     assert(sizeof(time_t) >= sizeof(long)); | ||||
|     time_t nearest = LONG_MAX; // nearest deadline
 | ||||
|     foreach (Children::iterator, i, children) { | ||||
|             if (i->second.monitorForSilence) { | ||||
|                 oldest = oldest == 0 || i->second.lastOutput < oldest | ||||
|                     ? i->second.lastOutput : oldest; | ||||
|         if (!i->second.respectTimeouts) continue; | ||||
|         if (settings.maxSilentTime != 0) | ||||
|             nearest = std::min(nearest, i->second.lastOutput + settings.maxSilentTime); | ||||
|         if (settings.buildTimeout != 0) | ||||
|             nearest = std::min(nearest, i->second.timeStarted + settings.buildTimeout); | ||||
|     } | ||||
|         } | ||||
|         if (oldest) { | ||||
|             time_t silenceTimeout = std::max((time_t) 0, oldest + settings.maxSilentTime - before); | ||||
|             timeout.tv_sec = useTimeout | ||||
|                 ? std::min(silenceTimeout, timeout.tv_sec) | ||||
|                 : silenceTimeout; | ||||
|     if (nearest != LONG_MAX) { | ||||
|         timeout.tv_sec = std::max((time_t) 1, nearest - before); | ||||
|         useTimeout = true; | ||||
|         printMsg(lvlVomit, format("sleeping %1% seconds") % timeout.tv_sec); | ||||
|     } | ||||
|     } | ||||
| 
 | ||||
|     /* If we are polling goals that are waiting for a lock, then wake
 | ||||
|        up after a few seconds at most. */ | ||||
|  | @ -3151,7 +3140,7 @@ void Worker::waitForInput() | |||
|         if (lastWokenUp == 0) | ||||
|             printMsg(lvlError, "waiting for locks or build slots..."); | ||||
|         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; | ||||
| 
 | ||||
|     using namespace std; | ||||
|  | @ -3175,9 +3164,6 @@ void Worker::waitForInput() | |||
| 
 | ||||
|     time_t after = time(0); | ||||
| 
 | ||||
|     /* Keep track of when we were last called.  */ | ||||
|     lastWait = after; | ||||
| 
 | ||||
|     /* Process all available file descriptors. */ | ||||
| 
 | ||||
|     /* Since goals may be canceled from inside the loop below (causing
 | ||||
|  | @ -3218,7 +3204,7 @@ void Worker::waitForInput() | |||
|         } | ||||
| 
 | ||||
|         if (settings.maxSilentTime != 0 && | ||||
|             j->second.monitorForSilence && | ||||
|             j->second.respectTimeouts && | ||||
|             after - j->second.lastOutput >= (time_t) settings.maxSilentTime) | ||||
|         { | ||||
|             printMsg(lvlError, | ||||
|  | @ -3228,7 +3214,8 @@ void Worker::waitForInput() | |||
|         } | ||||
| 
 | ||||
|         if (settings.buildTimeout != 0 && | ||||
|             after - before >= (time_t) settings.buildTimeout) | ||||
|             j->second.respectTimeouts && | ||||
|             after - j->second.timeStarted >= (time_t) settings.buildTimeout) | ||||
|         { | ||||
|             printMsg(lvlError, | ||||
|                 format("%1% timed out after %2% seconds") | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue