871 self.stop_everywhere = False |
872 self.stop_everywhere = False |
872 |
873 |
873 self.isBroken = True |
874 self.isBroken = True |
874 self.isException = True |
875 self.isException = True |
875 |
876 |
|
877 disassembly = None |
876 stack = [] |
878 stack = [] |
877 if exctb: |
879 if exctb: |
878 frlist = self.__extract_stack(exctb) |
880 frlist = self.__extract_stack(exctb) |
879 frlist.reverse() |
881 frlist.reverse() |
|
882 disassembly = self.__disassemble(frlist[0][0]) |
880 |
883 |
881 self.currentFrame = frlist[0][0] |
884 self.currentFrame = frlist[0][0] |
882 stack = self.getStack(frlist[self.skipFrames:]) |
885 stack = self.getStack(frlist[self.skipFrames:]) |
883 |
886 |
884 self._dbgClient.lockClient() |
887 self._dbgClient.lockClient() |
885 self._dbgClient.currentThread = self |
888 self._dbgClient.currentThread = self |
886 self._dbgClient.currentThreadExec = self |
889 self._dbgClient.currentThreadExec = self |
887 self._dbgClient.sendException(exctypetxt, excvaltxt, stack) |
890 self._dbgClient.sendException(exctypetxt, excvaltxt, stack) |
|
891 self._dbgClient.setDisassembly(disassembly) |
888 self._dbgClient.dumpThreadList() |
892 self._dbgClient.dumpThreadList() |
889 |
893 |
890 if exctb is not None: |
894 if exctb is not None: |
891 # When polling kept enabled, it isn't possible to resume after an |
895 # When polling kept enabled, it isn't possible to resume after an |
892 # unhandled exception without further user interaction. |
896 # unhandled exception without further user interaction. |
927 stack.append((tb.tb_frame, tb.tb_lineno)) |
931 stack.append((tb.tb_frame, tb.tb_lineno)) |
928 tb = tb.tb_next |
932 tb = tb.tb_next |
929 tb = None |
933 tb = None |
930 return stack |
934 return stack |
931 |
935 |
|
936 def __disassemble(self, frame): |
|
937 """ |
|
938 Private method to generate a disassembly of the given code object. |
|
939 |
|
940 @param frame frame object to be disassembled |
|
941 @type code |
|
942 @return dictionary containing the disassembly information |
|
943 @rtype dict |
|
944 """ |
|
945 co = frame.f_code |
|
946 disDict = { |
|
947 "lasti": frame.f_lasti, |
|
948 "firstlineno": co.co_firstlineno, |
|
949 "instructions": [], |
|
950 } |
|
951 |
|
952 # 1. disassembly info |
|
953 for instr in dis.get_instructions(co): |
|
954 instrDict = { |
|
955 "lineno": |
|
956 0 if instr.starts_line is None else instr.starts_line, |
|
957 "isJumpTarget": instr.is_jump_target, |
|
958 "offset": instr.offset, |
|
959 "opname": instr.opname, |
|
960 "arg": instr.arg, |
|
961 "argrepr": instr.argrepr, |
|
962 } |
|
963 disDict["instructions"].append(instrDict) |
|
964 |
|
965 # 2. code info |
|
966 # Note: keep in sync with PythonDisViewer.__createCodeInfo() |
|
967 disDict["codeinfo"] = { |
|
968 "name": co.co_name, |
|
969 "filename": co.co_filename, |
|
970 "firstlineno": co.co_firstlineno, |
|
971 "argcount": co.co_argcount, |
|
972 "kwonlyargcount": co.co_kwonlyargcount, |
|
973 "nlocals": co.co_nlocals, |
|
974 "stacksize": co.co_stacksize, |
|
975 "flags": dis.pretty_flags(co.co_flags), |
|
976 "consts": [str(const) for const in co.co_consts], |
|
977 "names": [str(name) for name in co.co_names], |
|
978 "varnames": [str(name) for name in co.co_varnames], |
|
979 "freevars": [str(var) for var in co.co_freevars], |
|
980 "cellvars": [str(var) for var in co.co_cellvars], |
|
981 } |
|
982 try: |
|
983 disDict["codeinfo"]["posonlyargcount"] = co.co_posonlyargcount |
|
984 except AttributeError: |
|
985 # does not exist prior to 3.8.0 |
|
986 disDict["codeinfo"]["posonlyargcount"] = 0 |
|
987 |
|
988 return disDict |
|
989 |
932 def __extractSystemExitMessage(self, excinfo): |
990 def __extractSystemExitMessage(self, excinfo): |
933 """ |
991 """ |
934 Private method to get the SystemExit code and message. |
992 Private method to get the SystemExit code and message. |
935 |
993 |
936 @param excinfo details about the SystemExit exception |
994 @param excinfo details about the SystemExit exception |