DebugClients/Python/ThreadExtension.py

branch
debugger speed
changeset 5208
aa8045780ce4
parent 5207
7283629b02c0
child 5209
cd058aa6af37
equal deleted inserted replaced
5207:7283629b02c0 5208:aa8045780ce4
35 self._original_start_new_thread = None 35 self._original_start_new_thread = None
36 36
37 self.clientLock = threading.RLock() 37 self.clientLock = threading.RLock()
38 38
39 # dictionary of all threads running {id: DebugBase} 39 # dictionary of all threads running {id: DebugBase}
40 self.threads = {} 40 self.threads = {_thread.get_ident(): self}
41 41
42 # the "current" thread, basically for variables view 42 # the "current" thread, basically for variables view
43 self.currentThread = self 43 self.currentThread = self
44 44
45 # special objects representing the main scripts thread and frame 45 # special objects representing the main scripts thread and frame
57 # provide a hook to perform a hard breakpoint 57 # provide a hook to perform a hard breakpoint
58 # Use it like this: 58 # Use it like this:
59 # if hasattr(sys, 'breakpoint): sys.breakpoint() 59 # if hasattr(sys, 'breakpoint): sys.breakpoint()
60 sys.breakpoint = self.set_trace 60 sys.breakpoint = self.set_trace
61 61
62 def attachThread(self, target=None, args=None, kwargs=None, 62 def attachThread(self, target=None, args=None, kwargs={},
63 mainThread=False): 63 mainThread=False):
64 """ 64 """
65 Public method to setup a thread for DebugClient to debug. 65 Public method to setup a standard thread for DebugClient to debug.
66 66
67 If mainThread is True, then we are attaching to the already 67 If mainThread is True, then we are attaching to the already
68 started mainthread of the app and the rest of the args are ignored. 68 started mainthread of the app and the rest of the args are ignored.
69 69
70 @param target the start function of the target thread (i.e. the 70 @param target the start function of the target thread (i.e. the user
71 user code) 71 code)
72 @param args arguments to pass to target 72 @param args arguments to pass to target
73 @param kwargs keyword arguments to pass to target 73 @param kwargs keyword arguments to pass to target
74 @param mainThread True, if we are attaching to the already 74 @param mainThread True, if we are attaching to the already
75 started mainthread of the app 75 started mainthread of the app
76 @return identifier of the created thread 76 @return identifier of the created thread
77 """ 77 """
78 return 78 if mainThread:
79 try: 79 ident = _thread.get_ident()
80 self.lockClient() 80 name = 'MainThread'
81 newThread = DebugThread(self, target, args, kwargs, mainThread) 81 newThread = self.mainThread
82 ident = -1 82 newThread._mainThread = True
83 if mainThread: 83 if self.debugging:
84 ident = _thread.get_ident() 84 sys.setprofile(newThread.profile)
85 self.mainThread = newThread 85
86 if self.debugging: 86 else:
87 sys.setprofile(newThread.profile) 87 newThread = DebugBase(self)
88 else: 88 ident = self._original_start_new_thread(
89 ident = _original_start_thread(newThread.bootstrap, ()) 89 newThread.bootstrap, (target, args, kwargs))
90 if self.mainThread is not None: 90 name = 'Thread-{0}'.format(self.threadNumber)
91 self.tracePython = self.mainThread.tracePython 91 self.threadNumber += 1
92 newThread.set_ident(ident) 92
93 self.threads[newThread.get_ident()] = newThread 93 newThread.id = ident
94 finally: 94 newThread.name = name
95 self.unlockClient() 95
96 self.threads[ident] = newThread
97
96 return ident 98 return ident
97 99
98 def threadTerminated(self, dbgThread): 100 def threadTerminated(self, dbgThread):
99 """ 101 """
100 Public method called when a DebugThread has exited. 102 Public method called when a DebugThread has exited.
150 def dumpThreadList(self): 152 def dumpThreadList(self):
151 """ 153 """
152 Public method to send the list of threads. 154 Public method to send the list of threads.
153 """ 155 """
154 threadList = [] 156 threadList = []
155 if self.threads and self.currentThread: 157 if len(self.threads) > 1:
156 # indication for the threaded debugger 158 currentId = _thread.get_ident()
157 currentId = self.currentThread.get_ident() 159 # update thread names set by user (threading.setName)
158 for t in self.threads.values(): 160 threadNames = {t.ident: t.getName() for t in threading.enumerate()}
159 d = {} 161
160 d["id"] = t.get_ident() 162 for id, thd in self.threads.items():
161 d["name"] = t.get_name() 163 d = {"id": id}
162 d["broken"] = t.isBroken 164 try:
165 d["name"] = threadNames.get(id, thd.name)
166 d["broken"] = thd.isBroken
167 except Exception:
168 d["name"] = 'UnknownThread'
169 d["broken"] = False
170
163 threadList.append(d) 171 threadList.append(d)
164 else: 172 else:
165 currentId = -1 173 currentId = -1
166 d = {} 174 d = {"id": -1}
167 d["id"] = -1
168 d["name"] = "MainThread" 175 d["name"] = "MainThread"
169 if hasattr(self, "isBroken"): 176 d["broken"] = self.isBroken
170 d["broken"] = self.isBroken
171 else:
172 d["broken"] = False
173 threadList.append(d) 177 threadList.append(d)
174 178
175 self.sendJsonCommand("ResponseThreadList", { 179 self.sendJsonCommand("ResponseThreadList", {
176 "currentID": currentId, 180 "currentID": currentId,
177 "threadList": threadList, 181 "threadList": threadList,

eric ide

mercurial