#!/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