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,31 +3115,22 @@ 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
 | ||||||
|  |     foreach (Children::iterator, i, children) { | ||||||
|  |         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 (nearest != LONG_MAX) { | ||||||
|     /* If we're monitoring for silence on stdout/stderr, sleep until
 |         timeout.tv_sec = std::max((time_t) 1, nearest - before); | ||||||
|        the first deadline for any child. */ |         useTimeout = true; | ||||||
|     if (settings.maxSilentTime != 0) { |         printMsg(lvlVomit, format("sleeping %1% seconds") % timeout.tv_sec); | ||||||
|         time_t oldest = 0; |  | ||||||
|         foreach (Children::iterator, i, children) { |  | ||||||
|             if (i->second.monitorForSilence) { |  | ||||||
|                 oldest = oldest == 0 || i->second.lastOutput < oldest |  | ||||||
|                     ? i->second.lastOutput : oldest; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         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; |  | ||||||
|             useTimeout = true; |  | ||||||
|             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
 | ||||||
|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue