Package PyFoam :: Package Execution :: Module FoamThread
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Execution.FoamThread

  1  #  ICE Revision: $Id: FoamThread.py 7962 2007-09-20 08:33:19Z bgschaid $  
  2  """Thread wrappers for OpenFOAM""" 
  3   
  4  import sys 
  5   
  6  from threading import Thread,Lock,Timer 
  7   
  8  if sys.version_info<(2,4): 
  9      from popen2 import Popen4 
 10  else: 
 11      import subprocess 
 12       
 13  from time import time,sleep 
 14  from resource import getrusage,getpagesize,RUSAGE_CHILDREN 
 15  from os import uname,kill,path,unlink 
 16  import signal 
 17   
 18  from PyFoam.Basics.LineReader import LineReader 
 19  from PyFoam.Infrastructure.Logging import foamLogger 
 20  from PyFoam.Error import warning 
 21   
22 -def checkForStopFile(thrd):
23 """Checks for the file 'stop' in the directory of the FoamRun. If 24 it exists it is removed and the run is stopped gracefully""" 25 26 fName=path.join(thrd.runner.dir,"stop") 27 28 if path.exists(fName): 29 unlink(fName) 30 thrd.runner.stopGracefully() 31 return 32 33 fName=path.join(thrd.runner.dir,"write") 34 35 if path.exists(fName): 36 unlink(fName) 37 thrd.runner.writeResults() 38 39 thrd.timer2=Timer(thrd.timerTime,checkForStopFile,args=[thrd]) 40 thrd.timer2.start()
41
42 -def getLinuxMem(thrd):
43 """Reads the Memory usage of a thread on a linux-System 44 45 @param thrd: the thread object in question""" 46 47 # print "Timer called" 48 49 if not thrd.isLinux or thrd.threadPid<0: 50 return 51 52 mem=0 53 54 try: 55 t=open('/proc/%d/status' % thrd.threadPid) 56 v=t.read() 57 t.close() 58 # f=open('/tmp/test%dstatus' % thrd.threadPid,'w') 59 # f.write(v) 60 # f.close() 61 62 i=v.index('VmRSS') 63 tmp=v[i:].split() 64 if len(tmp)>=3: 65 mem=long(tmp[1]) 66 if tmp[2].lower()=='kb': 67 mem*=1024 68 elif tmp[2].lower()=='mb': 69 mem*=1024*1024 70 else: 71 mem=-1 72 except Exception,e: 73 print "Getting LinuxMem:",e 74 mem=-1 75 76 if mem>thrd.linuxMaxMem: 77 # print "Setting Memory to: ",mem 78 thrd.linuxMaxMem=mem 79 80 # print "Restarting Timer" 81 82 thrd.timer=Timer(thrd.timerTime,getLinuxMem,args=[thrd]) 83 thrd.timer.start()
84
85 -class FoamThread(Thread):
86 """Thread running an OpenFOAM command 87 88 The output of the command can be accessed in a thread-safe manner, 89 line by line 90 91 Designed to be used by the BasicRunner-class""" 92
93 - def __init__(self,cmdline,runner):
94 """@param cmdline:cmdline - Command line of the OpenFOAM command 95 @param runner: the Runner-object that started this thread""" 96 Thread.__init__(self) 97 self.cmdline=cmdline 98 self.runner=runner 99 self.output=None 100 self.reader=LineReader() 101 102 self.isLinux=False 103 self.isDarwin=False 104 self.threadPid=-1 105 self.who=RUSAGE_CHILDREN 106 107 if uname()[0]=="Linux": 108 self.isLinux=True 109 self.linuxMaxMem=0 110 elif uname()[0]=="Darwin": 111 self.isDarwin=True 112 113 self.resStart=None 114 self.resEnd=None 115 116 self.timeStart=None 117 self.timeEnd=None 118 119 self.timerTime=5. 120 121 self.stateLock=Lock() 122 self.setState(False) 123 124 self.status=None 125 126 self.lineLock=Lock() 127 self.line="" 128 129 self.stateLock.acquire()
130
131 - def run(self):
132 """start the command""" 133 # print "Starting ",self.cmdline 134 self.resStart=getrusage(self.who) 135 self.timeStart=time() 136 137 if sys.version_info<(2,4): 138 run=Popen4(self.cmdline) 139 self.output=run.fromchild 140 else: 141 run=subprocess.Popen(self.cmdline,shell=True,bufsize=0, 142 stdin=subprocess.PIPE,stdout=subprocess.PIPE, 143 stderr=subprocess.STDOUT,close_fds=True) 144 self.output=run.stdout 145 self.threadPid=run.pid 146 foamLogger().info("Started with PID %d" % self.threadPid) 147 if self.isLinux: 148 # print "Starting Timer" 149 self.timer=Timer(0.1*self.timerTime,getLinuxMem,args=[self]) 150 self.timer.start() 151 152 # print "Starting Timer" 153 self.timer2=Timer(0.5*self.timerTime,checkForStopFile,args=[self]) 154 self.timer2.start() 155 156 self.hasSomethingToSay=True 157 self.stateLock.release() 158 159 try: 160 # print "Waiting",time() 161 self.status=run.wait() 162 # Python 2.3 on Mac OS X never seems to reach this point 163 # print "After wait",time() 164 # print "Status:",self.status 165 166 # to give a chance to read the remaining output 167 if self.hasSomethingToSay: 168 sleep(2.) 169 170 while self.reader.read(self.output): 171 print "Unused output:",self.reader.line 172 except OSError,e: 173 print "Exeption caught:",e 174 175 self.stopTimer() 176 177 self.threadPid=-1 178 179 self.resEnd=getrusage(self.who) 180 self.timeEnd=time()
181 # print "End:",self.timeEnd 182 # print "Returned",self.status 183
184 - def stopTimer(self):
185 if self.isLinux: 186 self.timer.cancel() 187 self.timer2.cancel()
188
189 - def read(self):
190 """read another line from the output""" 191 self.setState(self.reader.read(self.output)) 192 self.lineLock.acquire() 193 self.line=self.reader.line 194 self.lineLock.release()
195
196 - def getLine(self):
197 """gets the last line from the output""" 198 self.lineLock.acquire() 199 val=self.line 200 self.lineLock.release() 201 202 return val
203
204 - def interrupt(self):
205 """A keyboard-interrupt is reported""" 206 self.reader.wasInterupted=True 207 self.setState(False)
208
209 - def setState(self,state):
210 """sets the state of the thread (is there any more output)""" 211 self.stateLock.acquire() 212 self.hasSomethingToSay=state 213 if not self.hasSomethingToSay and self.timeStart and self.reader.wasInterupted: 214 if self.threadPid>0: 215 msg="Killing PID %d" % self.threadPid 216 print msg 217 foamLogger().warning(msg) 218 try: 219 kill(self.threadPid,signal.SIGKILL) 220 except OSError: 221 warning("Process",self.threadPid,"was already dead") 222 223 # print "Set: ",state 224 self.stateLock.release()
225
226 - def check(self):
227 """@return: False if there is no more output of the command""" 228 self.stateLock.acquire() 229 state=self.hasSomethingToSay 230 # print "Get: ",state 231 self.stateLock.release() 232 233 return state
234
235 - def cpuTime(self):
236 """@return: number of seconds CPU-Time used""" 237 return self.cpuUserTime()+self.cpuSystemTime()
238
239 - def cpuUserTime(self):
240 """@return: number of seconds CPU-Time used in user mode""" 241 if self.resEnd==None: # and self.isDarwin: 242 # Mac OS X needs this (Ubuntu too?) 243 self.resEnd=getrusage(self.who) 244 if self.resStart==None or self.resEnd==None: 245 return 0 246 else: 247 return self.resEnd.ru_utime-self.resStart.ru_utime
248
249 - def cpuSystemTime(self):
250 """@return: number of seconds CPU-Time used in system mode""" 251 if self.resEnd==None: # and self.isDarwin: 252 # Mac OS X needs this (Ubuntu too?) 253 self.resEnd=getrusage(self.who) 254 if self.resStart==None or self.resEnd==None: 255 return 0 256 else: 257 return self.resEnd.ru_stime-self.resStart.ru_stime
258
259 - def usedMemory(self):
260 """@return: maximum resident set size in MegaByte""" 261 scale=1024.*1024. 262 if self.isLinux: 263 return self.linuxMaxMem/scale 264 265 if self.resStart==None or self.resEnd==None: 266 return 0. 267 else: 268 return getpagesize()*(self.resEnd.ru_maxrss-self.resStart.ru_maxrss)/scale
269
270 - def wallTime(self):
271 """@return: the wall-clock-time needed by the process""" 272 if self.timeEnd==None: # and self.isDarwin: 273 # Mac OS X needs this (Ubuntu too?) 274 self.timeEnd=time() 275 276 self.timeEnd=time() 277 278 # print "Wall:",self.timeEnd,self.timeStart 279 if self.timeStart==None or self.timeEnd==None: 280 return 0 281 else: 282 return self.timeEnd-self.timeStart
283