DebugClients/Python3/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__
510 self.attachThread(mainThread=True) 512 self.attachThread(mainThread=True)
511 513
512 # set the system exception handling function to ensure, that 514 # set the system exception handling function to ensure, that
513 # we report on all unhandled exceptions 515 # we report on all unhandled exceptions
514 sys.excepthook = self.__unhandled_exception 516 sys.excepthook = self.__unhandled_exception
517 self.__interceptSignals()
515 518
516 # clear all old breakpoints, they'll get set after we have 519 # clear all old breakpoints, they'll get set after we have
517 # started 520 # started
518 self.mainThread.clear_all_breaks() 521 self.mainThread.clear_all_breaks()
519 522
555 self.attachThread(mainThread=True) 558 self.attachThread(mainThread=True)
556 559
557 # set the system exception handling function to ensure, that 560 # set the system exception handling function to ensure, that
558 # we report on all unhandled exceptions 561 # we report on all unhandled exceptions
559 sys.excepthook = self.__unhandled_exception 562 sys.excepthook = self.__unhandled_exception
563 self.__interceptSignals()
560 564
561 self.mainThread.tracePython = False 565 self.mainThread.tracePython = False
562 566
563 self.debugMod.__dict__['__file__'] = sys.argv[0] 567 self.debugMod.__dict__['__file__'] = sys.argv[0]
564 sys.modules['__main__'] = self.debugMod 568 sys.modules['__main__'] = self.debugMod
569 exec(code, self.debugMod.__dict__) 573 exec(code, self.debugMod.__dict__)
570 except SystemExit as exc: 574 except SystemExit as exc:
571 res = exc.code 575 res = exc.code
572 atexit._run_exitfuncs() 576 atexit._run_exitfuncs()
573 self.writestream.flush() 577 self.writestream.flush()
574 self.progTerminated(res) 578 self.progTerminated(res, exit=True)
575 return 579 return
576 580
577 if cmd == DebugProtocol.RequestProfile: 581 if cmd == DebugProtocol.RequestProfile:
578 sys.setprofile(None) 582 sys.setprofile(None)
579 import PyProfile 583 import PyProfile
589 os.chdir(wd) 593 os.chdir(wd)
590 594
591 # set the system exception handling function to ensure, that 595 # set the system exception handling function to ensure, that
592 # we report on all unhandled exceptions 596 # we report on all unhandled exceptions
593 sys.excepthook = self.__unhandled_exception 597 sys.excepthook = self.__unhandled_exception
598 self.__interceptSignals()
594 599
595 # generate a profile object 600 # generate a profile object
596 self.prof = PyProfile.PyProfile(sys.argv[0]) 601 self.prof = PyProfile.PyProfile(sys.argv[0])
597 602
598 if int(erase): 603 if int(erase):
614 except SystemExit as exc: 619 except SystemExit as exc:
615 res = exc.code 620 res = exc.code
616 atexit._run_exitfuncs() 621 atexit._run_exitfuncs()
617 self.prof.save() 622 self.prof.save()
618 self.writestream.flush() 623 self.writestream.flush()
619 self.progTerminated(res) 624 self.progTerminated(res, exit=True)
620 return 625 return
621 626
622 if cmd == DebugProtocol.RequestCoverage: 627 if cmd == DebugProtocol.RequestCoverage:
623 from coverage import coverage 628 from coverage import coverage
624 sys.argv = [] 629 sys.argv = []
633 os.chdir(wd) 638 os.chdir(wd)
634 639
635 # set the system exception handling function to ensure, that 640 # set the system exception handling function to ensure, that
636 # we report on all unhandled exceptions 641 # we report on all unhandled exceptions
637 sys.excepthook = self.__unhandled_exception 642 sys.excepthook = self.__unhandled_exception
643 self.__interceptSignals()
638 644
639 # generate a coverage object 645 # generate a coverage object
640 self.cover = coverage( 646 self.cover = coverage(
641 auto_data=True, 647 auto_data=True,
642 data_file="{0}.coverage".format( 648 data_file="{0}.coverage".format(
665 res = exc.code 671 res = exc.code
666 atexit._run_exitfuncs() 672 atexit._run_exitfuncs()
667 self.cover.stop() 673 self.cover.stop()
668 self.cover.save() 674 self.cover.save()
669 self.writestream.flush() 675 self.writestream.flush()
670 self.progTerminated(res) 676 self.progTerminated(res, exit=True)
671 return 677 return
672 678
673 if cmd == DebugProtocol.RequestShutdown: 679 if cmd == DebugProtocol.RequestShutdown:
674 self.sessionClose() 680 self.sessionClose()
675 return 681 return
857 failed = eval(failed) 863 failed = eval(failed)
858 864
859 # set the system exception handling function to ensure, that 865 # set the system exception handling function to ensure, that
860 # we report on all unhandled exceptions 866 # we report on all unhandled exceptions
861 sys.excepthook = self.__unhandled_exception 867 sys.excepthook = self.__unhandled_exception
868 self.__interceptSignals()
862 869
863 try: 870 try:
864 import unittest 871 import unittest
865 utModule = imp.load_source(tn, fn) 872 utModule = imp.load_source(tn, fn)
866 try: 873 try:
1168 @param excval data about the exception 1175 @param excval data about the exception
1169 @param exctb traceback for the exception 1176 @param exctb traceback for the exception
1170 """ 1177 """
1171 self.mainThread.user_exception(None, (exctype, excval, exctb), True) 1178 self.mainThread.user_exception(None, (exctype, excval, exctb), True)
1172 1179
1180 def __interceptSignals(self):
1181 """
1182 Private method to intercept common signals.
1183 """
1184 for signum in [
1185 signal.SIGABRT, # abnormal termination
1186 signal.SIGFPE, # floating point exception
1187 signal.SIGILL, # illegal instruction
1188 signal.SIGSEGV, # segmentation violation
1189 ]:
1190 signal.signal(signum, self.__signalHandler)
1191
1192 def __signalHandler(self, signalNumber, stackFrame):
1193 """
1194 Private method to handle signals.
1195
1196 @param signalNumber number of the signal to be handled
1197 @type int
1198 @param stack frame current stack frame
1199 @type frame object
1200 """
1201 if signalNumber == signal.SIGABRT:
1202 message = "Abnormal Termination"
1203 elif signalNumber == signal.SIGFPE:
1204 message = "Floating Point Exception"
1205 elif signalNumber == signal.SIGILL:
1206 message = "Illegal Instruction"
1207 elif signalNumber == signal.SIGSEGV:
1208 message = "Segmentation Violation"
1209 else:
1210 message = "Unknown Signal '{0}'".format(signalNumber)
1211
1212 filename = self.absPath(stackFrame)
1213
1214 linenr = stackFrame.f_lineno
1215 ffunc = stackFrame.f_code.co_name
1216
1217 if ffunc == '?':
1218 ffunc = ''
1219
1220 if ffunc and not ffunc.startswith("<"):
1221 argInfo = inspect.getargvalues(stackFrame)
1222 try:
1223 fargs = inspect.formatargvalues(
1224 argInfo.args, argInfo.varargs,
1225 argInfo.keywords, argInfo.locals)
1226 except Exception:
1227 fargs = ""
1228 else:
1229 fargs = ""
1230
1231 siglist = [message, [filename, linenr, ffunc, fargs]]
1232
1233 self.write("{0}{1}".format(DebugProtocol.ResponseSignal, str(siglist)))
1234
1173 def absPath(self, fn): 1235 def absPath(self, fn):
1174 """ 1236 """
1175 Public method to convert a filename to an absolute name. 1237 Public method to convert a filename to an absolute name.
1176 1238
1177 sys.path is used as a set of possible prefixes. The name stays 1239 sys.path is used as a set of possible prefixes. The name stays
1241 1303
1242 @return flag indicating a running debug session (boolean) 1304 @return flag indicating a running debug session (boolean)
1243 """ 1305 """
1244 return self.running 1306 return self.running
1245 1307
1246 def progTerminated(self, status): 1308 def progTerminated(self, status, exit=False):
1247 """ 1309 """
1248 Public method to tell the debugger that the program has terminated. 1310 Public method to tell the debugger that the program has terminated.
1249 1311
1250 @param status the return status 1312 @param status return status
1313 @param exit flag indicating to perform a sys.exit()
1314 @type bool
1251 """ 1315 """
1252 if status is None: 1316 if status is None:
1253 status = 0 1317 status = 0
1254 else: 1318 else:
1255 try: 1319 try:
1259 1323
1260 if self.running: 1324 if self.running:
1261 self.set_quit() 1325 self.set_quit()
1262 self.running = None 1326 self.running = None
1263 self.write('{0}{1:d}\n'.format(DebugProtocol.ResponseExit, status)) 1327 self.write('{0}{1:d}\n'.format(DebugProtocol.ResponseExit, status))
1328 if exit:
1329 sys.exit(status)
1264 1330
1265 # reset coding 1331 # reset coding
1266 self.__coding = self.defaultCoding 1332 self.__coding = self.defaultCoding
1267 1333
1268 def __dumpVariables(self, frmnr, scope, filter): 1334 def __dumpVariables(self, frmnr, scope, filter):
1948 self.mainThread.tracePython = tracePython 2014 self.mainThread.tracePython = tracePython
1949 2015
1950 # set the system exception handling function to ensure, that 2016 # set the system exception handling function to ensure, that
1951 # we report on all unhandled exceptions 2017 # we report on all unhandled exceptions
1952 sys.excepthook = self.__unhandled_exception 2018 sys.excepthook = self.__unhandled_exception
2019 self.__interceptSignals()
1953 2020
1954 # now start debugging 2021 # now start debugging
1955 if enableTrace: 2022 if enableTrace:
1956 self.mainThread.set_trace() 2023 self.mainThread.set_trace()
1957 2024
2005 self.mainThread.tracePython = tracePython 2072 self.mainThread.tracePython = tracePython
2006 2073
2007 # set the system exception handling function to ensure, that 2074 # set the system exception handling function to ensure, that
2008 # we report on all unhandled exceptions 2075 # we report on all unhandled exceptions
2009 sys.excepthook = self.__unhandled_exception 2076 sys.excepthook = self.__unhandled_exception
2077 self.__interceptSignals()
2010 2078
2011 # This will eventually enter a local event loop. 2079 # This will eventually enter a local event loop.
2012 # Note the use of backquotes to cause a repr of self.running. The 2080 # Note the use of backquotes to cause a repr of self.running. The
2013 # need for this is on Windows os where backslash is the path separator. 2081 # need for this is on Windows os where backslash is the path separator.
2014 # They will get inadvertantly stripped away during the eval causing 2082 # They will get inadvertantly stripped away during the eval causing

eric ide

mercurial