56 """Thread running an OpenFOAM command
57
58 The output of the command can be accessed in a thread-safe manner,
59 line by line
60
61 Designed to be used by the BasicRunner-class"""
62
64 """cmdline - Command line of the OpenFOAM command"""
65 Thread.__init__(self)
66 self.cmdline=cmdline
67 self.output=None
68 self.reader=LineReader()
69
70 self.isLinux=False
71 self.isDarwin=False
72 self.threadPid=-1
73 self.who=RUSAGE_CHILDREN
74
75 if uname()[0]=="Linux":
76 self.isLinux=True
77 self.linuxMaxMem=0
78 elif uname()[0]=="Darwin":
79 self.isDarwin=True
80
81
82 self.resStart=None
83 self.resEnd=None
84
85 self.timeStart=None
86 self.timeEnd=None
87
88 self.timerTime=5.
89
90 self.stateLock=Lock()
91 self.setState(False)
92
93 self.status=None
94
95 self.lineLock=Lock()
96 self.line=""
97
98 self.stateLock.acquire()
99
101 """start the command"""
102
103 self.resStart=getrusage(self.who)
104 self.timeStart=time()
105
106 run=Popen4(self.cmdline)
107 self.output=run.fromchild
108 self.threadPid=run.pid
109 foamLogger().info("Started with PID %d" % self.threadPid)
110 if self.isLinux:
111
112 self.timer=Timer(0.1*self.timerTime,getLinuxMem,args=[self])
113 self.timer.start()
114
115 self.hasSomethingToSay=True
116 self.stateLock.release()
117
118 try:
119
120 self.status=run.wait()
121
122
123
124
125
126 if self.hasSomethingToSay:
127 sleep(2.)
128
129 while self.reader.read(self.output):
130 print "Unused output:",self.reader.line
131 except OSError,e:
132 print "Exeption caught:",e
133
134 self.stopTimer()
135
136 self.threadPid=-1
137
138 self.resEnd=getrusage(self.who)
139 self.timeEnd=time()
140
141
142
144 if self.isLinux:
145 self.timer.cancel()
146
148 """read another line from the output"""
149 self.setState(self.reader.read(self.output))
150 self.lineLock.acquire()
151 self.line=self.reader.line
152 self.lineLock.release()
153
155 """gets the last line from the output"""
156 self.lineLock.acquire()
157 val=self.line
158 self.lineLock.release()
159
160 return val
161
163 """A keyboard-interrupt is reported"""
164 self.reader.wasInterupted=True
165 self.setState(False)
166
168 """sets the state of the thread (is there any more output)"""
169 self.stateLock.acquire()
170 self.hasSomethingToSay=state
171 if not self.hasSomethingToSay and self.timeStart and self.reader.wasInterupted:
172 if self.threadPid>0:
173 msg="Killing PID %d" % self.threadPid
174 print msg
175 foamLogger().warning(msg)
176 kill(self.threadPid,signal.SIGKILL)
177
178 self.stateLock.release()
179
181 """@return: False if there is no more output of the command"""
182 self.stateLock.acquire()
183 state=self.hasSomethingToSay
184
185 self.stateLock.release()
186
187 return state
188
192
194 """@return: number of seconds CPU-Time used in user mode"""
195 if self.resEnd==None:
196
197 self.resEnd=getrusage(self.who)
198 if self.resStart==None or self.resEnd==None:
199 return 0
200 else:
201 return self.resEnd.ru_utime-self.resStart.ru_utime
202
204 """@return: number of seconds CPU-Time used in system mode"""
205 if self.resEnd==None:
206
207 self.resEnd=getrusage(self.who)
208 if self.resStart==None or self.resEnd==None:
209 return 0
210 else:
211 return self.resEnd.ru_stime-self.resStart.ru_stime
212
214 """@return: maximum resident set size in MegaByte"""
215 scale=1024.*1024.
216 if self.isLinux:
217 return self.linuxMaxMem/scale
218
219 if self.resStart==None or self.resEnd==None:
220 return 0.
221 else:
222 return getpagesize()*(self.resEnd.ru_maxrss-self.resStart.ru_maxrss)/scale
223
225 """@return: the wall-clock-time needed by the process"""
226 if self.timeEnd==None:
227
228 self.timeEnd=time()
229
230 self.timeEnd=time()
231
232
233 if self.timeStart==None or self.timeEnd==None:
234 return 0
235 else:
236 return self.timeEnd-self.timeStart