DebugClients/Python/DebugClientBase.py

changeset 4366
9445c7cb991f
parent 4309
cc9c62f55413
child 4370
54dbb658f9e6
diff -r d97f2e05ae1b -r 9445c7cb991f DebugClients/Python/DebugClientBase.py
--- a/DebugClients/Python/DebugClientBase.py	Sun Aug 16 12:24:28 2015 +0200
+++ b/DebugClients/Python/DebugClientBase.py	Sun Aug 16 13:47:44 2015 +0200
@@ -17,6 +17,8 @@
 import imp
 import re
 import atexit
+import signal
+import inspect
 
 
 import DebugProtocol
@@ -521,6 +523,7 @@
                 # set the system exception handling function to ensure, that
                 # we report on all unhandled exceptions
                 sys.excepthook = self.__unhandled_exception
+                self.__interceptSignals()
                 
                 # clear all old breakpoints, they'll get set after we
                 # have started
@@ -566,6 +569,7 @@
                 # set the system exception handling function to ensure, that
                 # we report on all unhandled exceptions
                 sys.excepthook = self.__unhandled_exception
+                self.__interceptSignals()
                 
                 self.mainThread.tracePython = 0
                 
@@ -578,7 +582,7 @@
                     res = exc.code
                     atexit._run_exitfuncs()
                 self.writestream.flush()
-                self.progTerminated(res)
+                self.progTerminated(res, exit=True)
                 return
 
             if cmd == DebugProtocol.RequestCoverage:
@@ -597,6 +601,7 @@
                 # set the system exception handling function to ensure, that
                 # we report on all unhandled exceptions
                 sys.excepthook = self.__unhandled_exception
+                self.__interceptSignals()
                 
                 # generate a coverage object
                 self.cover = coverage(
@@ -619,7 +624,7 @@
                 self.cover.stop()
                 self.cover.save()
                 self.writestream.flush()
-                self.progTerminated(res)
+                self.progTerminated(res, exit=True)
                 return
             
             if cmd == DebugProtocol.RequestProfile:
@@ -639,6 +644,7 @@
                 # set the system exception handling function to ensure, that
                 # we report on all unhandled exceptions
                 sys.excepthook = self.__unhandled_exception
+                self.__interceptSignals()
                 
                 # generate a profile object
                 self.prof = PyProfile.PyProfile(sys.argv[0])
@@ -656,7 +662,7 @@
                     atexit._run_exitfuncs()
                 self.prof.save()
                 self.writestream.flush()
-                self.progTerminated(res)
+                self.progTerminated(res, exit=True)
                 return
 
             if cmd == DebugProtocol.RequestShutdown:
@@ -849,6 +855,7 @@
                 # set the system exception handling function to ensure, that
                 # we report on all unhandled exceptions
                 sys.excepthook = self.__unhandled_exception
+                self.__interceptSignals()
                 
                 try:
                     import unittest
@@ -1158,6 +1165,61 @@
         @param exctb traceback for the exception
         """
         self.mainThread.user_exception(None, (exctype, excval, exctb), 1)
+    
+    def __interceptSignals(self):
+        """
+        Private method to intercept common signals.
+        """
+        for signum in [
+            signal.SIGABRT,                 # abnormal termination
+            signal.SIGFPE,                  # floating point exception
+            signal.SIGILL,                  # illegal instruction
+            signal.SIGSEGV,                 # segmentation violation
+        ]:
+            signal.signal(signum, self.__signalHandler)
+    
+    def __signalHandler(self, signalNumber, stackFrame):
+        """
+        Private method to handle signals.
+        
+        @param signalNumber number of the signal to be handled
+        @type int
+        @param stack frame current stack frame
+        @type frame object
+        """
+        if signalNumber == signal.SIGABRT:
+            message = "Abnormal Termination"
+        elif signalNumber == signal.SIGFPE:
+            message = "Floating Point Exception"
+        elif signalNumber == signal.SIGILL:
+            message = "Illegal Instruction"
+        elif signalNumber == signal.SIGSEGV:
+            message = "Segmentation Violation"
+        else:
+            message = "Unknown Signal '%d'" % signalNumber
+        
+        filename = self.absPath(stackFrame)
+        
+        linenr = stackFrame.f_lineno
+        ffunc = stackFrame.f_code.co_name
+        
+        if ffunc == '?':
+            ffunc = ''
+        
+        if ffunc and not ffunc.startswith("<"):
+            argInfo = inspect.getargvalues(stackFrame)
+            try:
+                fargs = inspect.formatargvalues(
+                    argInfo.args, argInfo.varargs,
+                    argInfo.keywords, argInfo.locals)
+            except Exception:
+                fargs = ""
+        else:
+            fargs = ""
+        
+        siglist = [message, [filename, linenr, ffunc, fargs]]
+        
+        self.write("%s%s" % (DebugProtocol.ResponseSignal, str(siglist)))
         
     def absPath(self, fn):
         """
@@ -1232,11 +1294,13 @@
         """
         return self.running
 
-    def progTerminated(self, status):
+    def progTerminated(self, status, exit=False):
         """
         Public method to tell the debugger that the program has terminated.
         
-        @param status the return status
+        @param status return status
+        @param exit flag indicating to perform a sys.exit()
+        @type bool
         """
         if status is None:
             status = 0
@@ -1250,6 +1314,8 @@
             self.set_quit()
             self.running = None
             self.write('%s%d\n' % (DebugProtocol.ResponseExit, status))
+            if exit:
+                sys.exit(status)
         
         # reset coding
         self.__coding = self.defaultCoding
@@ -1891,6 +1957,7 @@
         # set the system exception handling function to ensure, that
         # we report on all unhandled exceptions
         sys.excepthook = self.__unhandled_exception
+        self.__interceptSignals()
         
         # now start debugging
         if enableTrace:
@@ -1948,6 +2015,7 @@
         # set the system exception handling function to ensure, that
         # we report on all unhandled exceptions
         sys.excepthook = self.__unhandled_exception
+        self.__interceptSignals()
         
         # This will eventually enter a local event loop.
         # Note the use of backquotes to cause a repr of self.running. The

eric ide

mercurial