#!/usr/bin/python
import os,time,sys
time_map = { "seconds" : 1,
"minutes" : 60,
"hours" : 3600,
"days" : 86400
}
def get_pid_status(pid):
#True is running, False is not running
ps_command = "ps -p " + str(pid)
popen_results = os.popen4(ps_command)
for line in popen_results[1]:
contents = line.split()
if contents[0] == str(pid):
return True
return False
def wallclock(command,lifetime=120,poll=1,repeat=0,time_unit="hours"):
#This prevents zombie problems
import signal
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
if time_unit not in time_map.keys():
print "This is not an accepted unit- treating as seconds. Acceptable units are:"
for item in time_map.keys():
print "\t" + item
else:
lifetime *= time_map[time_unit]
poll *= time_map[time_unit]
#The wallclock subroutine is written to run a command, but kill it and rerun it if doesn't finish in a certain time period (or after a given number of repeats
#It is a "dumb" command- it should behave as a simple replacement for most "os.system()" calls, but with extra options
pid = os.fork()
if pid == 0:
#child process- run the command and exit
os.setpgrp() # Sets process session leader.
os.system(command)
#print "Child process command executed. I should exit"
sys.stdout.flush()
#This requires SIGCHLD to be set to SIG_IGN, to prevent a zombie process from appearing
os._exit(0)
else:
current_time = 0
while(current_time < lifetime):
if get_pid_status(pid):
#print "Child process " +str(pid) +" is running and I will sleep for " + str(poll) + " seconds"
time.sleep(poll)
current_time += poll
else:
#print "Parent process should now finish and return you"
signal.signal(signal.SIGCHLD, signal.SIG_DFL)
return 1
#If you end up here, time has run out and the program has not finished: recurse & repeat (if required)
#signal.signal(signal.SIGCHLD, signal.SIG_DFL)
if repeat > 0:
repeat -= 1
os.kill(-pid,signal.SIGKILL)
signal.signal(signal.SIGCHLD, signal.SIG_DFL)
return wallclock(command,lifetime=lifetime,poll=poll,time_unit=time_unit,repeat=repeat)
else:
#give up, kill child and return 0
os.kill(-pid,signal.SIGKILL)
signal.signal(signal.SIGCHLD, signal.SIG_DFL)
return 0