DebugClients/Python/DebugClientBase.py

changeset 4366
9445c7cb991f
parent 4309
cc9c62f55413
child 4370
54dbb658f9e6
equal deleted inserted replaced
4365:d97f2e05ae1b 4366:9445c7cb991f
15 import os 15 import os
16 import time 16 import time
17 import imp 17 import imp
18 import re 18 import re
19 import atexit 19 import atexit
20 import signal
21 import inspect
20 22
21 23
22 import DebugProtocol 24 import DebugProtocol
23 import DebugClientCapabilities 25 import DebugClientCapabilities
24 from DebugBase import setRecursionLimit, printerr # __IGNORE_WARNING__ 26 from DebugBase import setRecursionLimit, printerr # __IGNORE_WARNING__
519 self.attachThread(mainThread=1) 521 self.attachThread(mainThread=1)
520 522
521 # set the system exception handling function to ensure, that 523 # set the system exception handling function to ensure, that
522 # we report on all unhandled exceptions 524 # we report on all unhandled exceptions
523 sys.excepthook = self.__unhandled_exception 525 sys.excepthook = self.__unhandled_exception
526 self.__interceptSignals()
524 527
525 # clear all old breakpoints, they'll get set after we 528 # clear all old breakpoints, they'll get set after we
526 # have started 529 # have started
527 self.mainThread.clear_all_breaks() 530 self.mainThread.clear_all_breaks()
528 531
564 self.attachThread(mainThread=1) 567 self.attachThread(mainThread=1)
565 568
566 # set the system exception handling function to ensure, that 569 # set the system exception handling function to ensure, that
567 # we report on all unhandled exceptions 570 # we report on all unhandled exceptions
568 sys.excepthook = self.__unhandled_exception 571 sys.excepthook = self.__unhandled_exception
572 self.__interceptSignals()
569 573
570 self.mainThread.tracePython = 0 574 self.mainThread.tracePython = 0
571 575
572 self.debugMod.__dict__['__file__'] = sys.argv[0] 576 self.debugMod.__dict__['__file__'] = sys.argv[0]
573 sys.modules['__main__'] = self.debugMod 577 sys.modules['__main__'] = self.debugMod
576 execfile(sys.argv[0], self.debugMod.__dict__) 580 execfile(sys.argv[0], self.debugMod.__dict__)
577 except SystemExit as exc: 581 except SystemExit as exc:
578 res = exc.code 582 res = exc.code
579 atexit._run_exitfuncs() 583 atexit._run_exitfuncs()
580 self.writestream.flush() 584 self.writestream.flush()
581 self.progTerminated(res) 585 self.progTerminated(res, exit=True)
582 return 586 return
583 587
584 if cmd == DebugProtocol.RequestCoverage: 588 if cmd == DebugProtocol.RequestCoverage:
585 from coverage import coverage 589 from coverage import coverage
586 sys.argv = [] 590 sys.argv = []
595 os.chdir(wd) 599 os.chdir(wd)
596 600
597 # set the system exception handling function to ensure, that 601 # set the system exception handling function to ensure, that
598 # we report on all unhandled exceptions 602 # we report on all unhandled exceptions
599 sys.excepthook = self.__unhandled_exception 603 sys.excepthook = self.__unhandled_exception
604 self.__interceptSignals()
600 605
601 # generate a coverage object 606 # generate a coverage object
602 self.cover = coverage( 607 self.cover = coverage(
603 auto_data=True, 608 auto_data=True,
604 data_file="%s.coverage" % os.path.splitext(sys.argv[0])[0]) 609 data_file="%s.coverage" % os.path.splitext(sys.argv[0])[0])
617 res = exc.code 622 res = exc.code
618 atexit._run_exitfuncs() 623 atexit._run_exitfuncs()
619 self.cover.stop() 624 self.cover.stop()
620 self.cover.save() 625 self.cover.save()
621 self.writestream.flush() 626 self.writestream.flush()
622 self.progTerminated(res) 627 self.progTerminated(res, exit=True)
623 return 628 return
624 629
625 if cmd == DebugProtocol.RequestProfile: 630 if cmd == DebugProtocol.RequestProfile:
626 sys.setprofile(None) 631 sys.setprofile(None)
627 import PyProfile 632 import PyProfile
637 os.chdir(wd) 642 os.chdir(wd)
638 643
639 # set the system exception handling function to ensure, that 644 # set the system exception handling function to ensure, that
640 # we report on all unhandled exceptions 645 # we report on all unhandled exceptions
641 sys.excepthook = self.__unhandled_exception 646 sys.excepthook = self.__unhandled_exception
647 self.__interceptSignals()
642 648
643 # generate a profile object 649 # generate a profile object
644 self.prof = PyProfile.PyProfile(sys.argv[0]) 650 self.prof = PyProfile.PyProfile(sys.argv[0])
645 651
646 if int(erase): 652 if int(erase):
654 except SystemExit as exc: 660 except SystemExit as exc:
655 res = exc.code 661 res = exc.code
656 atexit._run_exitfuncs() 662 atexit._run_exitfuncs()
657 self.prof.save() 663 self.prof.save()
658 self.writestream.flush() 664 self.writestream.flush()
659 self.progTerminated(res) 665 self.progTerminated(res, exit=True)
660 return 666 return
661 667
662 if cmd == DebugProtocol.RequestShutdown: 668 if cmd == DebugProtocol.RequestShutdown:
663 self.sessionClose() 669 self.sessionClose()
664 return 670 return
847 failed = eval(failed) 853 failed = eval(failed)
848 854
849 # set the system exception handling function to ensure, that 855 # set the system exception handling function to ensure, that
850 # we report on all unhandled exceptions 856 # we report on all unhandled exceptions
851 sys.excepthook = self.__unhandled_exception 857 sys.excepthook = self.__unhandled_exception
858 self.__interceptSignals()
852 859
853 try: 860 try:
854 import unittest 861 import unittest
855 utModule = __import__(tn) 862 utModule = __import__(tn)
856 try: 863 try:
1156 @param exctype the type of the exception 1163 @param exctype the type of the exception
1157 @param excval data about the exception 1164 @param excval data about the exception
1158 @param exctb traceback for the exception 1165 @param exctb traceback for the exception
1159 """ 1166 """
1160 self.mainThread.user_exception(None, (exctype, excval, exctb), 1) 1167 self.mainThread.user_exception(None, (exctype, excval, exctb), 1)
1168
1169 def __interceptSignals(self):
1170 """
1171 Private method to intercept common signals.
1172 """
1173 for signum in [
1174 signal.SIGABRT, # abnormal termination
1175 signal.SIGFPE, # floating point exception
1176 signal.SIGILL, # illegal instruction
1177 signal.SIGSEGV, # segmentation violation
1178 ]:
1179 signal.signal(signum, self.__signalHandler)
1180
1181 def __signalHandler(self, signalNumber, stackFrame):
1182 """
1183 Private method to handle signals.
1184
1185 @param signalNumber number of the signal to be handled
1186 @type int
1187 @param stack frame current stack frame
1188 @type frame object
1189 """
1190 if signalNumber == signal.SIGABRT:
1191 message = "Abnormal Termination"
1192 elif signalNumber == signal.SIGFPE:
1193 message = "Floating Point Exception"
1194 elif signalNumber == signal.SIGILL:
1195 message = "Illegal Instruction"
1196 elif signalNumber == signal.SIGSEGV:
1197 message = "Segmentation Violation"
1198 else:
1199 message = "Unknown Signal '%d'" % signalNumber
1200
1201 filename = self.absPath(stackFrame)
1202
1203 linenr = stackFrame.f_lineno
1204 ffunc = stackFrame.f_code.co_name
1205
1206 if ffunc == '?':
1207 ffunc = ''
1208
1209 if ffunc and not ffunc.startswith("<"):
1210 argInfo = inspect.getargvalues(stackFrame)
1211 try:
1212 fargs = inspect.formatargvalues(
1213 argInfo.args, argInfo.varargs,
1214 argInfo.keywords, argInfo.locals)
1215 except Exception:
1216 fargs = ""
1217 else:
1218 fargs = ""
1219
1220 siglist = [message, [filename, linenr, ffunc, fargs]]
1221
1222 self.write("%s%s" % (DebugProtocol.ResponseSignal, str(siglist)))
1161 1223
1162 def absPath(self, fn): 1224 def absPath(self, fn):
1163 """ 1225 """
1164 Public method to convert a filename to an absolute name. 1226 Public method to convert a filename to an absolute name.
1165 1227
1230 1292
1231 @return flag indicating a running debug session (boolean) 1293 @return flag indicating a running debug session (boolean)
1232 """ 1294 """
1233 return self.running 1295 return self.running
1234 1296
1235 def progTerminated(self, status): 1297 def progTerminated(self, status, exit=False):
1236 """ 1298 """
1237 Public method to tell the debugger that the program has terminated. 1299 Public method to tell the debugger that the program has terminated.
1238 1300
1239 @param status the return status 1301 @param status return status
1302 @param exit flag indicating to perform a sys.exit()
1303 @type bool
1240 """ 1304 """
1241 if status is None: 1305 if status is None:
1242 status = 0 1306 status = 0
1243 else: 1307 else:
1244 try: 1308 try:
1248 1312
1249 if self.running: 1313 if self.running:
1250 self.set_quit() 1314 self.set_quit()
1251 self.running = None 1315 self.running = None
1252 self.write('%s%d\n' % (DebugProtocol.ResponseExit, status)) 1316 self.write('%s%d\n' % (DebugProtocol.ResponseExit, status))
1317 if exit:
1318 sys.exit(status)
1253 1319
1254 # reset coding 1320 # reset coding
1255 self.__coding = self.defaultCoding 1321 self.__coding = self.defaultCoding
1256 1322
1257 def __dumpVariables(self, frmnr, scope, filter): 1323 def __dumpVariables(self, frmnr, scope, filter):
1889 self.mainThread.tracePython = tracePython 1955 self.mainThread.tracePython = tracePython
1890 1956
1891 # set the system exception handling function to ensure, that 1957 # set the system exception handling function to ensure, that
1892 # we report on all unhandled exceptions 1958 # we report on all unhandled exceptions
1893 sys.excepthook = self.__unhandled_exception 1959 sys.excepthook = self.__unhandled_exception
1960 self.__interceptSignals()
1894 1961
1895 # now start debugging 1962 # now start debugging
1896 if enableTrace: 1963 if enableTrace:
1897 self.mainThread.set_trace() 1964 self.mainThread.set_trace()
1898 1965
1946 self.mainThread.tracePython = tracePython 2013 self.mainThread.tracePython = tracePython
1947 2014
1948 # set the system exception handling function to ensure, that 2015 # set the system exception handling function to ensure, that
1949 # we report on all unhandled exceptions 2016 # we report on all unhandled exceptions
1950 sys.excepthook = self.__unhandled_exception 2017 sys.excepthook = self.__unhandled_exception
2018 self.__interceptSignals()
1951 2019
1952 # This will eventually enter a local event loop. 2020 # This will eventually enter a local event loop.
1953 # Note the use of backquotes to cause a repr of self.running. The 2021 # Note the use of backquotes to cause a repr of self.running. The
1954 # need for this is on Windows os where backslash is the path separator. 2022 # need for this is on Windows os where backslash is the path separator.
1955 # They will get inadvertantly stripped away during the eval causing 2023 # They will get inadvertantly stripped away during the eval causing

eric ide

mercurial