157 |
158 |
158 def dumpThreadList(self): |
159 def dumpThreadList(self): |
159 """ |
160 """ |
160 Public method to send the list of threads. |
161 Public method to send the list of threads. |
161 """ |
162 """ |
|
163 self.updateThreadList() |
162 threadList = [] |
164 threadList = [] |
163 if len(self.threads) > 1: |
165 if len(self.threads) > 1: |
164 currentId = _thread.get_ident() |
166 currentId = _thread.get_ident() |
165 # update thread names set by user (threading.setName) |
167 # update thread names set by user (threading.setName) |
166 threadNames = {t.ident: t.getName() for t in threading.enumerate()} |
168 threadNames = {t.ident: t.getName() for t in threading.enumerate()} |
185 self.sendJsonCommand("ResponseThreadList", { |
187 self.sendJsonCommand("ResponseThreadList", { |
186 "currentID": currentId, |
188 "currentID": currentId, |
187 "threadList": threadList, |
189 "threadList": threadList, |
188 }) |
190 }) |
189 |
191 |
|
192 def getExecutedFrame(self, frame): |
|
193 """ |
|
194 Public method to return the currently executed frame. |
|
195 |
|
196 @param frame the current frame |
|
197 @type frame object |
|
198 @return the frame which is excecuted (without debugger frames) |
|
199 @rtype frame object |
|
200 """ |
|
201 # to get the currently executed frame, skip all frames belonging to the |
|
202 # debugger |
|
203 while frame is not None: |
|
204 baseName = os.path.basename(frame.f_code.co_filename) |
|
205 if not baseName.startswith( |
|
206 ('DebugClientBase.py', 'DebugBase.py', 'AsyncIO.py', |
|
207 'ThreadExtension.py', 'threading.py')): |
|
208 break |
|
209 frame = frame.f_back |
|
210 |
|
211 return frame |
|
212 |
|
213 def updateThreadList(self): |
|
214 """ |
|
215 Public method to update the list of running threads. |
|
216 """ |
|
217 frames = sys._current_frames() |
|
218 for id, frame in frames.items(): |
|
219 # skip our own timer thread |
|
220 if frame.f_code.co_name == '__eventPollTimer': |
|
221 continue |
|
222 |
|
223 # Unknown thread |
|
224 if id not in self.threads: |
|
225 newThread = DebugBase(self) |
|
226 name = 'Thread-{0}'.format(self.threadNumber) |
|
227 self.threadNumber += 1 |
|
228 |
|
229 newThread.id = id |
|
230 newThread.name = name |
|
231 self.threads[id] = newThread |
|
232 |
|
233 # adjust current frame |
|
234 self.threads[id].currentFrame = self.getExecutedFrame(frame) |
|
235 |
|
236 # Clean up obsolet because terminated threads |
|
237 self.threads = {id_: thrd for id_, thrd in self.threads.items() |
|
238 if id_ in frames} |
|
239 |
190 def find_module(self, fullname, path=None): |
240 def find_module(self, fullname, path=None): |
191 """ |
241 """ |
192 Public method returning the module loader. |
242 Public method returning the module loader. |
193 |
243 |
194 @param fullname name of the module to be loaded |
244 @param fullname name of the module to be loaded |