* While waiting for a lock, print a sign of life every 5 minutes.
This prevents remote builders from being killed by the `max-silent-time' inactivity monitor while they are waiting for a long garbage collection to finish. This happens fairly often in the Hydra build farm.
This commit is contained in:
		
							parent
							
								
									c45de33c67
								
							
						
					
					
						commit
						f859a8d3c3
					
				
					 3 changed files with 27 additions and 3 deletions
				
			
		| 
						 | 
					@ -31,6 +31,11 @@ static void sigintHandler(int signo)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void sigalrmHandler(int signo)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Path makeRootName(const Path & gcRoot, int & counter)
 | 
					Path makeRootName(const Path & gcRoot, int & counter)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    counter++;
 | 
					    counter++;
 | 
				
			||||||
| 
						 | 
					@ -160,6 +165,14 @@ static void initAndRun(int argc, char * * argv)
 | 
				
			||||||
    if (sigaction(SIGPIPE, &act, 0))
 | 
					    if (sigaction(SIGPIPE, &act, 0))
 | 
				
			||||||
        throw SysError("ignoring SIGPIPE");
 | 
					        throw SysError("ignoring SIGPIPE");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Catch SIGALRM with an empty handler (we just need it to get an
 | 
				
			||||||
 | 
					       EINTR from blocking system calls). */
 | 
				
			||||||
 | 
					    act.sa_handler = sigalrmHandler;
 | 
				
			||||||
 | 
					    sigfillset(&act.sa_mask);
 | 
				
			||||||
 | 
					    act.sa_flags = 0;
 | 
				
			||||||
 | 
					    if (sigaction(SIGALRM, &act, 0))
 | 
				
			||||||
 | 
					        throw SysError("installing handler for SIGALRM");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Reset SIGCHLD to its default. */
 | 
					    /* Reset SIGCHLD to its default. */
 | 
				
			||||||
    act.sa_handler = SIG_DFL;
 | 
					    act.sa_handler = SIG_DFL;
 | 
				
			||||||
    act.sa_flags = 0;
 | 
					    act.sa_flags = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,8 @@ void deleteLockFile(const Path & path, int fd)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool lockFile(int fd, LockType lockType, bool wait)
 | 
					bool lockFile(int fd, LockType lockType, bool wait,
 | 
				
			||||||
 | 
					    unsigned int progressInterval)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct flock lock;
 | 
					    struct flock lock;
 | 
				
			||||||
    if (lockType == ltRead) lock.l_type = F_RDLCK;
 | 
					    if (lockType == ltRead) lock.l_type = F_RDLCK;
 | 
				
			||||||
| 
						 | 
					@ -49,11 +50,20 @@ bool lockFile(int fd, LockType lockType, bool wait)
 | 
				
			||||||
    lock.l_len = 0; /* entire file */
 | 
					    lock.l_len = 0; /* entire file */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (wait) {
 | 
					    if (wait) {
 | 
				
			||||||
        while (fcntl(fd, F_SETLKW, &lock) != 0) {
 | 
					        /* Wait until we acquire the lock.  If `progressInterval' is
 | 
				
			||||||
 | 
					           non-zero, when print a message every `progressInterval'
 | 
				
			||||||
 | 
					           seconds.  This is mostly to make sure that remote builders
 | 
				
			||||||
 | 
					           aren't killed due to the `max-silent-time' inactivity
 | 
				
			||||||
 | 
					           monitor while waiting for the garbage collector lock. */
 | 
				
			||||||
 | 
					        while (1) {
 | 
				
			||||||
 | 
					            if (progressInterval) alarm(progressInterval);
 | 
				
			||||||
 | 
					            if (fcntl(fd, F_SETLKW, &lock) == 0) break;
 | 
				
			||||||
            checkInterrupt();
 | 
					            checkInterrupt();
 | 
				
			||||||
            if (errno != EINTR)
 | 
					            if (errno != EINTR)
 | 
				
			||||||
                throw SysError(format("acquiring/releasing lock"));
 | 
					                throw SysError(format("acquiring/releasing lock"));
 | 
				
			||||||
 | 
					            if (progressInterval) printMsg(lvlError, "still waiting for lock...");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        alarm(0);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        while (fcntl(fd, F_SETLK, &lock) != 0) {
 | 
					        while (fcntl(fd, F_SETLK, &lock) != 0) {
 | 
				
			||||||
            checkInterrupt();
 | 
					            checkInterrupt();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,8 @@ void deleteLockFile(const Path & path, int fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum LockType { ltRead, ltWrite, ltNone };
 | 
					enum LockType { ltRead, ltWrite, ltNone };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool lockFile(int fd, LockType lockType, bool wait);
 | 
					bool lockFile(int fd, LockType lockType, bool wait,
 | 
				
			||||||
 | 
					    unsigned int progressInterval = 300);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PathLocks 
 | 
					class PathLocks 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue