feature request: mock --timeout
Michael E Brown
Michael_E_Brown at dell.com
Thu Apr 19 06:14:32 UTC 2007
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 )
More information about the Fedora-buildsys-list
mailing list