DebugClients/Python/DebugBase.py

branch
debugger speed
changeset 5209
cd058aa6af37
parent 5208
aa8045780ce4
child 5221
960afd19c1b6
--- a/DebugClients/Python/DebugBase.py	Thu Oct 06 22:51:04 2016 +0200
+++ b/DebugClients/Python/DebugBase.py	Fri Oct 07 22:50:48 2016 +0200
@@ -74,7 +74,8 @@
         """
         self._dbgClient = dbgClient
         
-        self._mainThread = True
+        # Some informations about the thread
+        self.isMainThread = False
         self.quitting = False
         self.id = -1
         self.name = ''
@@ -321,10 +322,12 @@
                 if self.stopframe and frame.f_code.co_flags & CO_GENERATOR:
                     return
                 # The program has finished if we have just left the first frame
-                if (frame == self.botframe and
-                        self._mainThread):
-                    atexit._run_exitfuncs()
-                    self._dbgClient.progTerminated(arg)
+                if frame == self.botframe:
+                    if self.isMainThread:
+                        atexit._run_exitfuncs()
+                        self._dbgClient.progTerminated(arg)
+                    else:
+                        self._dbgClient.threadTerminated(self.id)
                 
                 if self.quitting and not self._dbgClient.passive:
                     raise SystemExit
@@ -384,8 +387,9 @@
         
         frame.f_trace = self.trace_dispatch
         while frame is not None:
-            # stop at erics debugger frame
-            if frame.f_back.f_code == stopOnHandleLine:
+            # stop at erics debugger frame or the threading bootstrap
+            if (frame.f_back.f_code == stopOnHandleLine or
+                    frame.f_back.f_code.co_name == bootstrap):
                 frame.f_trace = self.trace_dispatch
                 self.botframe = frame
                 break
@@ -396,24 +400,37 @@
         sys.settrace(self.trace_dispatch)
         sys.setprofile(self._dbgClient.callTraceEnabled)
     
-    def bootstrap(self):
+    def bootstrap(self, target, args, kwargs):
         """
-        Public method to bootstrap the thread.
+        Public method to bootstrap a thread.
         
         It wraps the call to the user function to enable tracing
         before hand.
+        
+        @param target function which is called in the new created thread
+        @type function pointer
+        @param args arguments to pass to target
+        @type tuple
+        @param kwargs keyword arguments to pass to target
+        @type dict
         """
         try:
-            self._threadRunning = True
-            self.traceThread()
-            self._target(*self._args, **self._kwargs)
+            frame = sys._getframe()
+            self.botframe = frame
+            # First time the dispach function is called, a "base debug"
+            # function has to be returned, which is called at every user code
+            # function call. Because of setting botframe manually, the
+            # specific branch returning the trace_dispatch itself is skipped.
+            # Because the next step is always in threading.py and we assume
+            # that there is no breakpoint in it, it's save to return
+            # trace_dispatch unconditionally.
+            sys.settrace(lambda frame, event, arg: self.trace_dispatch)
+            frame.f_trace = self.trace_dispatch
+            
+            target(*args, **kwargs)
         except SystemExit:
             pass
         finally:
-            self._threadRunning = False
-            self.quitting = True
-            self._dbgClient.threadTerminated(self)
-            sys.settrace(None)
             sys.setprofile(None)
     
     def run(self, cmd, globals=None, locals=None):

eric ide

mercurial