13 from DebugThread import * |
13 from DebugThread import * |
14 from DebugBase import * |
14 from DebugBase import * |
15 import DebugClientBase |
15 import DebugClientBase |
16 |
16 |
17 |
17 |
18 def _debugclient_start_new_thread(target, args, kwargs = {}): |
18 def _debugclient_start_new_thread(target, args, kwargs={}): |
19 """ |
19 """ |
20 Module function used to allow for debugging of multiple threads. |
20 Module function used to allow for debugging of multiple threads. |
21 |
21 |
22 The way it works is that below, we reset _thread._start_new_thread to |
22 The way it works is that below, we reset _thread._start_new_thread to |
23 this function object. Thus, providing a hook for us to see when |
23 this function object. Thus, providing a hook for us to see when |
24 threads are started. From here we forward the request onto the |
24 threads are started. From here we forward the request onto the |
25 DebugClient which will create a DebugThread object to allow tracing |
25 DebugClient which will create a DebugThread object to allow tracing |
26 of the thread then start up the thread. These actions are always |
26 of the thread then start up the thread. These actions are always |
27 performed in order to allow dropping into debug mode. |
27 performed in order to allow dropping into debug mode. |
28 |
28 |
29 See DebugClientThreads.attachThread and DebugThread.DebugThread in |
29 See DebugClientThreads.attachThread and DebugThread.DebugThread in |
30 DebugThread.py |
30 DebugThread.py |
31 |
31 |
32 @param target the start function of the target thread (i.e. the user code) |
32 @param target the start function of the target thread (i.e. the user code) |
33 @param args arguments to pass to target |
33 @param args arguments to pass to target |
34 @param kwargs keyword arguments to pass to target |
34 @param kwargs keyword arguments to pass to target |
37 if DebugClientBase.DebugClientInstance is not None: |
37 if DebugClientBase.DebugClientInstance is not None: |
38 return DebugClientBase.DebugClientInstance.attachThread(target, args, kwargs) |
38 return DebugClientBase.DebugClientInstance.attachThread(target, args, kwargs) |
39 else: |
39 else: |
40 return _original_start_thread(target, args, kwargs) |
40 return _original_start_thread(target, args, kwargs) |
41 |
41 |
42 # make _thread hooks available to system |
42 # make _thread hooks available to system |
43 _original_start_thread = _thread.start_new_thread |
43 _original_start_thread = _thread.start_new_thread |
44 _thread.start_new_thread = _debugclient_start_new_thread |
44 _thread.start_new_thread = _debugclient_start_new_thread |
45 |
45 |
46 # NOTE: import threading here AFTER above hook, as threading cache's |
46 # NOTE: import threading here AFTER above hook, as threading cache's |
47 # thread._start_new_thread. |
47 # thread._start_new_thread. |
48 from threading import RLock |
48 from threading import RLock |
|
49 |
49 |
50 |
50 class DebugClientThreads(DebugClientBase.DebugClientBase, AsyncIO): |
51 class DebugClientThreads(DebugClientBase.DebugClientBase, AsyncIO): |
51 """ |
52 """ |
52 Class implementing the client side of the debugger. |
53 Class implementing the client side of the debugger. |
53 |
54 |
72 self.mainThread = None |
73 self.mainThread = None |
73 self.mainFrame = None |
74 self.mainFrame = None |
74 |
75 |
75 self.variant = 'Threaded' |
76 self.variant = 'Threaded' |
76 |
77 |
77 def attachThread(self, target = None, args = None, kwargs = None, mainThread = False): |
78 def attachThread(self, target=None, args=None, kwargs=None, mainThread=False): |
78 """ |
79 """ |
79 Public method to setup a thread for DebugClient to debug. |
80 Public method to setup a thread for DebugClient to debug. |
80 |
81 |
81 If mainThread is non-zero, then we are attaching to the already |
82 If mainThread is non-zero, then we are attaching to the already |
82 started mainthread of the app and the rest of the args are ignored. |
83 started mainthread of the app and the rest of the args are ignored. |
83 |
84 |
84 @param target the start function of the target thread (i.e. the user code) |
85 @param target the start function of the target thread (i.e. the user code) |
85 @param args arguments to pass to target |
86 @param args arguments to pass to target |
86 @param kwargs keyword arguments to pass to target |
87 @param kwargs keyword arguments to pass to target |
87 @param mainThread True, if we are attaching to the already |
88 @param mainThread True, if we are attaching to the already |
88 started mainthread of the app |
89 started mainthread of the app |
89 @return identifier of the created thread |
90 @return identifier of the created thread |
90 """ |
91 """ |
91 try: |
92 try: |
92 self.lockClient() |
93 self.lockClient() |
153 else: |
154 else: |
154 self.currentThread = self.threads[id] |
155 self.currentThread = self.threads[id] |
155 finally: |
156 finally: |
156 self.unlockClient() |
157 self.unlockClient() |
157 |
158 |
158 def eventLoop(self, disablePolling = False): |
159 def eventLoop(self, disablePolling=False): |
159 """ |
160 """ |
160 Public method implementing our event loop. |
161 Public method implementing our event loop. |
161 |
162 |
162 @param disablePolling flag indicating to enter an event loop with |
163 @param disablePolling flag indicating to enter an event loop with |
163 polling disabled (boolean) |
164 polling disabled (boolean) |