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

Source Code for Module PyFoam.Execution.FoamThread

  1  #  ICE Revision: $Id: /local/openfoam/Python/PyFoam/PyFoam/Execution/FoamThread.py 5282 2009-07-24T12:39:30.467524Z 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 self.returncode=None 126 127 self.lineLock=Lock() 128 self.line="" 129 130 self.stateLock.acquire()
131
132 - def run(self):
133 """start the command""" 134 # print "Starting ",self.cmdline 135 self.resStart=getrusage(self.who) 136 self.timeStart=time() 137 138 if sys.version_info<(2,4): 139 run=Popen4(self.cmdline) 140 self.output=run.fromchild 141 else: 142 run=subprocess.Popen(self.cmdline,shell=True,bufsize=0, 143 stdin=subprocess.PIPE,stdout=subprocess.PIPE, 144 stderr=subprocess.STDOUT,close_fds=True) 145 self.output=run.stdout 146 self.run=run 147 self.threadPid=run.pid 148 foamLogger().info("Started with PID %d" % self.threadPid) 149 if self.isLinux: 150 # print "Starting Timer" 151 self.timer=Timer(0.1*self.timerTime,getLinuxMem,args=[self]) 152 self.timer.start() 153 154 # print "Starting Timer" 155 self.timer2=Timer(0.5*self.timerTime,checkForStopFile,args=[self]) 156 self.timer2.start() 157 158 self.hasSomethingToSay=True 159 self.stateLock.release() 160 161 try: 162 # print "Waiting",time() 163 self.status=run.wait() 164 # Python 2.3 on Mac OS X never seems to reach this point 165 # print "After wait",time() 166 # print "Status:",self.status 167 168 # to give a chance to read the remaining output 169 if self.hasSomethingToSay: 170 sleep(2.) 171 while self.reader.read(self.output): 172 print "Unused output:",self.reader.line 173 except OSError,e: 174 print "Exeption caught:",e 175 176 self.stopTimer() 177 178 self.threadPid=-1 179 180 self.resEnd=getrusage(self.who) 181 self.timeEnd=time() 182 # print "End:",self.timeEnd 183 # print "Returned",self.status 184 185 self.getReturnCode()
186
187 - def getReturnCode(self):
188 if sys.version_info<(2,4): 189 # Don't know how to get the returncode from a Popen4-object 190 self.returncode=0 191 else: 192 self.returncode=self.run.returncode 193 return self.returncode
194
195 - def stopTimer(self):
196 if self.isLinux: 197 self.timer.cancel() 198 self.timer2.cancel()
199
200 - def read(self):
201 """read another line from the output""" 202 self.setState(self.reader.read(self.output)) 203 self.lineLock.acquire() 204 self.line=self.reader.line 205 self.lineLock.release()
206
207 - def getLine(self):
208 """gets the last line from the output""" 209 self.lineLock.acquire() 210 val=self.line 211 self.lineLock.release() 212 213 return val
214
215 - def interrupt(self):
216 """A keyboard-interrupt is reported""" 217 self.reader.wasInterupted=True 218 self.setState(False)
219
220 - def setState(self,state):
221 """sets the state of the thread (is there any more output)""" 222 self.stateLock.acquire() 223 self.hasSomethingToSay=state 224 if not self.hasSomethingToSay and self.timeStart and self.reader.wasInterupted: 225 if self.threadPid>0: 226 msg="Killing PID %d" % self.threadPid 227 print msg 228 foamLogger().warning(msg) 229 try: 230 kill(self.threadPid,signal.SIGKILL) 231 except OSError: 232 warning("Process",self.threadPid,"was already dead") 233 234 # print "Set: ",state 235 self.stateLock.release()
236
237 - def check(self):
238 """@return: False if there is no more output of the command""" 239 self.stateLock.acquire() 240 state=self.hasSomethingToSay 241 # print "Get: ",state 242 self.stateLock.release() 243 244 return state
245
246 - def cpuTime(self):
247 """@return: number of seconds CPU-Time used""" 248 return self.cpuUserTime()+self.cpuSystemTime()
249
250 - def cpuUserTime(self):
251 """@return: number of seconds CPU-Time used in user mode""" 252 if self.resEnd==None: # and self.isDarwin: 253 # Mac OS X needs this (Ubuntu too?) 254 self.resEnd=getrusage(self.who) 255 if self.resStart==None or self.resEnd==None: 256 return 0 257 else: 258 return self.resEnd.ru_utime-self.resStart.ru_utime
259
260 - def cpuSystemTime(self):
261 """@return: number of seconds CPU-Time used in system mode""" 262 if self.resEnd==None: # and self.isDarwin: 263 # Mac OS X needs this (Ubuntu too?) 264 self.resEnd=getrusage(self.who) 265 if self.resStart==None or self.resEnd==None: 266 return 0 267 else: 268 return self.resEnd.ru_stime-self.resStart.ru_stime
269
270 - def usedMemory(self):
271 """@return: maximum resident set size in MegaByte""" 272 scale=1024.*1024. 273 if self.isLinux: 274 return self.linuxMaxMem/scale 275 276 if self.resStart==None or self.resEnd==None: 277 return 0. 278 else: 279 return getpagesize()*(self.resEnd.ru_maxrss-self.resStart.ru_maxrss)/scale
280
281 - def wallTime(self):
282 """@return: the wall-clock-time needed by the process""" 283 if self.timeEnd==None: # and self.isDarwin: 284 # Mac OS X needs this (Ubuntu too?) 285 self.timeEnd=time() 286 287 self.timeEnd=time() 288 289 # print "Wall:",self.timeEnd,self.timeStart 290 if self.timeStart==None or self.timeEnd==None: 291 return 0 292 else: 293 return self.timeEnd-self.timeStart
294