On Mon, Apr 16, 2007 at 01:07:52PM -0500, Michael E Brown wrote:
On Mon, Apr 16, 2007 at 12:50:11PM -0500, Clark Williams wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Matt Domsch wrote:
> > I'd like to make a feature request for mock: the ability for it to
> > determine a job has taken too long and kill it. mock --timeout N (with N
> > in minutes) is the UI I'm picturing.
> >
> >
> > I've been doing these mass rebuilds for a while. Every so often we'll
> > wind up with a package with the halting problem - it continues to run,
> > or not, but it doesn't ever finish building either. Ever. Several
> > days later, it's still going, but not making progress.
> >
> > Sure, some jobs, like the kernel, openoffice, glibc, etc. can take a
> > good number of hours. But even those don't run for days. The latest
> > culprits was a few perl modules that ran for >2 days with no end in
> > sight.
> >
>
> File an RFE BZ on it and I'll look at it.
I have some python code from another project that does exactly this. I
can drop it in. I'll send a patch for review.
here is my previous code to call an external command with a timeout.
I'll do a patch when I get a minute, but this should give a good idea:
# helper class & functions for executeCommand()
# User should handle this if they specify a timeout
class commandTimeoutExpired(Exception): pass
# the problem with os.system() is that the command that is run gets any
# keyboard input and/or signals. This means that <CTRL>-C interrupts the
# sub-program instead of the python program. This helper function fixes
# that.
# It also allows us to set up a maximum timeout before all children are
# killed
def executeCommand(cmd, timeout=0):
class alarmExc(Exception): pass
def alarmhandler(signum,stackframe):
raise alarmExc("timeout expired")
pid = os.fork()
if pid:
#parent
rpid = ret = 0
oldhandler=signal.signal(signal.SIGALRM,alarmhandler)
starttime = time.time()
prevTimeout = signal.alarm(timeout)
try:
(rpid, ret) = os.waitpid(pid, 0)
signal.alarm(0)
signal.signal(signal.SIGALRM,oldhandler)
if prevTimeout:
passed = time.time() - starttime
signal.alarm(math.ceil(prevTimeout - passed))
except alarmExc:
os.kill(-pid, signal.SIGTERM)
time.sleep(1)
os.kill(-pid, signal.SIGKILL)
(rpid, ret) = os.waitpid(pid, 0)
signal.signal(signal.SIGALRM,oldhandler)
if prevTimeout:
passed = time.time() - starttime
signal.alarm(max(math.ceil(prevTimeout - passed), 1))
raise commandTimeoutExpired( "Specified timeout of %s
seconds expired before command finished. Command was: %s"
% (timeout, cmd)
)
# mask and return just return value
return (ret & 0xFF00) >> 8
else:
#child
os.setpgrp() # become process group leader so that we can kill
all our children
ret = os.system(cmd)
os._exit( (ret & 0xFF00) >> 8 )