#NEWLINE# def Exec( cmd , env = None , timeout = 0 , waitfor = 0 ) : #NEWLINE# #INDENT# 'Executes a process and returns exit code, stdout, stderr.\n\n  Args:\n    cmd: str or sequence, command and optional arguments to execute.\n    env: dict, optional, environment variables to set.\n    timeout: int or float, if >0, Exec() will stop waiting for output\n      after timeout seconds and kill the process it started.  return code\n      might be undefined, or -SIGTERM, use waitfor to make sure to obtain it.\n      values <1 will be crudely rounded off because of select() sleep time.\n    waitfor: int or float, if >0, Exec() will wait waitfor seconds\n      before asking for the process exit status one more time.\n  Returns:\n    Tuple. (Integer return code, string standard out, string standard error).\n  ' #NEWLINE# if isinstance ( cmd , basestring ) : #NEWLINE# #INDENT# shell = True #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# shell = False #NEWLINE# #UNINDENT# if env : #NEWLINE# #INDENT# environ = os . environ . copy ( ) #NEWLINE# environ . update ( env ) #NEWLINE# env = environ #NEWLINE# #UNINDENT# p = subprocess . Popen ( cmd , env = env , stdout = subprocess . PIPE , stderr = subprocess . PIPE , shell = shell ) #NEWLINE# if ( timeout <= 0 ) : #NEWLINE# #INDENT# ( stdout , stderr ) = p . communicate ( ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# inactive = 0 #NEWLINE# stdout = [ ] #NEWLINE# stderr = [ ] #NEWLINE# SetFileNonBlocking ( p . stdout ) #NEWLINE# SetFileNonBlocking ( p . stderr ) #NEWLINE# returncode = None #NEWLINE# while ( returncode is None ) : #NEWLINE# #INDENT# ( rlist , _ , _ ) = select . select ( [ p . stdout , p . stderr ] , [ ] , [ ] , 1.0 ) #NEWLINE# if ( not rlist ) : #NEWLINE# #INDENT# inactive += 1 #NEWLINE# if ( inactive >= timeout ) : #NEWLINE# #INDENT# logging . error ( 'cmd has timed out: %s' , cmd ) #NEWLINE# logging . error ( 'Sending SIGTERM to PID=%s' , p . pid ) #NEWLINE# os . kill ( p . pid , signal . SIGTERM ) #NEWLINE# break #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# inactive = 0 #NEWLINE# for fd in rlist : #NEWLINE# #INDENT# if ( fd is p . stdout ) : #NEWLINE# #INDENT# stdout . append ( fd . read ( ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( fd is p . stderr ) : #NEWLINE# #INDENT# stderr . append ( fd . read ( ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# returncode = p . poll ( ) #NEWLINE# #UNINDENT# if ( ( inactive >= timeout ) and ( waitfor > 0 ) ) : #NEWLINE# #INDENT# time . sleep ( waitfor ) #NEWLINE# #UNINDENT# returncode = p . poll ( ) #NEWLINE# stdout = '' . join ( stdout ) #NEWLINE# stderr = '' . join ( stderr ) #NEWLINE# #UNINDENT# return ( p . returncode , stdout , stderr )