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

Source Code for Module PyFoam.Execution.FoamThread

  1  #  ICE Revision: $Id: FoamThread.py 8275 2007-12-10 09:40:38Z 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 while self.reader.read(self.output): 170 print "Unused output:",self.reader.line 171 except OSError,e: 172 print "Exeption caught:",e 173 174 self.stopTimer() 175 176 self.threadPid=-1 177 178 self.resEnd=getrusage(self.who) 179 self.timeEnd=time()
180 # print "End:",self.timeEnd 181 # print "Returned",self.status 182
183 - def stopTimer(self):
184 if self.isLinux: 185 self.timer.cancel() 186 self.timer2.cancel()
187
188 - def read(self):
189 """read another line from the output""" 190 self.setState(self.reader.read(self.output)) 191 self.lineLock.acquire() 192 self.line=self.reader.line 193 self.lineLock.release()
194
195 - def getLine(self):
196 """gets the last line from the output""" 197 self.lineLock.acquire() 198 val=self.line 199 self.lineLock.release() 200 201 return val
202
203 - def interrupt(self):
204 """A keyboard-interrupt is reported""" 205 self.reader.wasInterupted=True 206 self.setState(False)
207
208 - def setState(self,state):
209 """sets the state of the thread (is there any more output)""" 210 self.stateLock.acquire() 211 self.hasSomethingToSay=state 212 if not self.hasSomethingToSay and self.timeStart and self.reader.wasInterupted: 213 if self.threadPid>0: 214 msg="Killing PID %d" % self.threadPid 215 print msg 216 foamLogger().warning(msg) 217 try: 218 kill(self.threadPid,signal.SIGKILL) 219 except OSError: 220 warning("Process",self.threadPid,"was already dead") 221 222 # print "Set: ",state 223 self.stateLock.release()
224
225 - def check(self):
226 """@return: False if there is no more output of the command""" 227 self.stateLock.acquire() 228 state=self.hasSomethingToSay 229 # print "Get: ",state 230 self.stateLock.release() 231 232 return state
233
234 - def cpuTime(self):
235 """@return: number of seconds CPU-Time used""" 236 return self.cpuUserTime()+self.cpuSystemTime()
237
238 - def cpuUserTime(self):
239 """@return: number of seconds CPU-Time used in user mode""" 240 if self.resEnd==None: # and self.isDarwin: 241 # Mac OS X needs this (Ubuntu too?) 242 self.resEnd=getrusage(self.who) 243 if self.resStart==None or self.resEnd==None: 244 return 0 245 else: 246 return self.resEnd.ru_utime-self.resStart.ru_utime
247
248 - def cpuSystemTime(self):
249 """@return: number of seconds CPU-Time used in system mode""" 250 if self.resEnd==None: # and self.isDarwin: 251 # Mac OS X needs this (Ubuntu too?) 252 self.resEnd=getrusage(self.who) 253 if self.resStart==None or self.resEnd==None: 254 return 0 255 else: 256 return self.resEnd.ru_stime-self.resStart.ru_stime
257
258 - def usedMemory(self):
259 """@return: maximum resident set size in MegaByte""" 260 scale=1024.*1024. 261 if self.isLinux: 262 return self.linuxMaxMem/scale 263 264 if self.resStart==None or self.resEnd==None: 265 return 0. 266 else: 267 return getpagesize()*(self.resEnd.ru_maxrss-self.resStart.ru_maxrss)/scale
268
269 - def wallTime(self):
270 """@return: the wall-clock-time needed by the process""" 271 if self.timeEnd==None: # and self.isDarwin: 272 # Mac OS X needs this (Ubuntu too?) 273 self.timeEnd=time() 274 275 self.timeEnd=time() 276 277 # print "Wall:",self.timeEnd,self.timeStart 278 if self.timeStart==None or self.timeEnd==None: 279 return 0 280 else: 281 return self.timeEnd-self.timeStart
282