From 476af99637a176d45c4d1cea53a03d436484f0fe Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 27 Nov 2010 00:56:18 +0100 Subject: [PATCH] Choose PyString/PyBytesObjectPtr according to python version + support signals terminating the inferior. --- .../Debugger/Tests/test_libcython_in_gdb.py | 14 ++++- Cython/Debugger/libcython.py | 31 ++++++---- Cython/Debugger/libpython.py | 62 +++++++++++-------- 3 files changed, 67 insertions(+), 40 deletions(-) diff --git a/Cython/Debugger/Tests/test_libcython_in_gdb.py b/Cython/Debugger/Tests/test_libcython_in_gdb.py index 85a580ff..7042d96f 100644 --- a/Cython/Debugger/Tests/test_libcython_in_gdb.py +++ b/Cython/Debugger/Tests/test_libcython_in_gdb.py @@ -70,6 +70,8 @@ class DebugTestCase(unittest.TestCase): except RuntimeError: pass + gdb.execute('set args -c "import codefile"') + libcython.cy.step.static_breakpoints.clear() libcython.cy.step.runtime_breakpoints.clear() libcython.cy.step.init_breakpoints() @@ -140,6 +142,13 @@ class TestBreak(DebugTestCase): assert 'def join(' in gdb.execute('cy run', to_string=True) +class TestKilled(DebugTestCase): + + def test_abort(self): + gdb.execute("set args -c 'import os; os.abort()'") + output = gdb.execute('cy run', to_string=True) + assert 'abort' in output.lower() + class DebugStepperTestCase(DebugTestCase): def step(self, varnames_and_values, source_line=None, lineno=None): @@ -291,6 +300,7 @@ def _main(): "debugging information. Either compile python with " "-g or get a debug build (configure with --with-pydebug).") warnings.warn(msg) + os._exit(1) else: m = __import__(__name__, fromlist=['']) tests = inspect.getmembers(m, inspect.isclass) @@ -311,4 +321,6 @@ def main(trace_code=False): ignoredirs=[sys.prefix, sys.exec_prefix]) tracer.runfunc(_main) else: - _main() \ No newline at end of file + _main() + +main() \ No newline at end of file diff --git a/Cython/Debugger/libcython.py b/Cython/Debugger/libcython.py index d5e17c93..a6142ab5 100644 --- a/Cython/Debugger/libcython.py +++ b/Cython/Debugger/libcython.py @@ -390,8 +390,9 @@ class CythonBase(object): def is_initialized(self, cython_func, local_name): cur_lineno = self.get_cython_lineno() - return (local_name in cython_func.arguments or - cur_lineno > cython_func.locals[local_name].lineno) + return (local_name in cython_func.arguments or + (local_name in cython_func.locals and + cur_lineno > cython_func.locals[local_name].lineno)) class SourceFileDescriptor(object): def __init__(self, filename, lexer, formatter=None): @@ -1077,18 +1078,16 @@ class CyLocals(CythonCommand): command_class = gdb.COMMAND_STACK completer_class = gdb.COMPLETE_NONE - def _print_if_initialized(self, cyvar, max_name_length, prefix=''): - if self.is_initialized(self.get_cython_function(), cyvar.name): - value = gdb.parse_and_eval(cyvar.cname) - if not value.is_optimized_out: - self.print_gdb_value(cyvar.name, value, max_name_length, prefix) - @dispatch_on_frame(c_command='info locals', python_command='py-locals') def invoke(self, args, from_tty): local_cython_vars = self.get_cython_function().locals max_name_length = len(max(local_cython_vars, key=len)) for name, cyvar in sorted(local_cython_vars.iteritems(), key=sortkey): - self._print_if_initialized(cyvar, max_name_length) + if self.is_initialized(self.get_cython_function(), cyvar.name): + value = gdb.parse_and_eval(cyvar.cname) + if not value.is_optimized_out: + self.print_gdb_value(cyvar.name, value, + max_name_length, '') class CyGlobals(CyLocals): @@ -1124,8 +1123,14 @@ class CyGlobals(CyLocals): print 'C globals:' for name, cyvar in sorted(module_globals.iteritems(), key=sortkey): if name not in seen: - self._print_if_initialized(cyvar, max_name_length, - prefix=' ') + try: + value = gdb.parse_and_eval(cyvar.cname) + except RuntimeError: + pass + else: + if not value.is_optimized_out: + self.print_gdb_value(cyvar.name, value, + max_name_length, ' ') class CyExec(CythonCommand, libpython.PyExec): @@ -1284,14 +1289,14 @@ class CyCValue(CyCName): try: cname = super(CyCValue, self).invoke(cyname, frame=frame) return gdb.parse_and_eval(cname) - except (gdb.GdbError, RuntimeError): + except (gdb.GdbError, RuntimeError), e: # variable exists but may not have been initialized yet, or may be # in the globals dict of the Cython module d = self.get_cython_globals_dict() if cyname in d: return d[cyname]._gdbval - raise gdb.GdbError("Variable %s not initialized yet." % cyname) + raise gdb.GdbError(str(e)) class CyLine(gdb.Function, CythonBase): diff --git a/Cython/Debugger/libpython.py b/Cython/Debugger/libpython.py index 653ee219..593cd580 100644 --- a/Cython/Debugger/libpython.py +++ b/Cython/Debugger/libpython.py @@ -332,7 +332,7 @@ class PyObjectPtr(object): #print 'tp_flags = 0x%08x' % tp_flags #print 'tp_name = %r' % tp_name - + name_map = {'bool': PyBoolObjectPtr, 'classobj': PyClassObjectPtr, 'instance': PyInstanceObjectPtr, @@ -357,7 +357,11 @@ class PyObjectPtr(object): if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS: return PyTupleObjectPtr if tp_flags & Py_TPFLAGS_STRING_SUBCLASS: - return PyStringObjectPtr + try: + gdb.lookup_type('PyBytesObject') + return PyBytesObject + except RuntimeError: + return PyStringObjectPtr if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS: return PyUnicodeObjectPtr if tp_flags & Py_TPFLAGS_DICT_SUBCLASS: @@ -380,7 +384,7 @@ class PyObjectPtr(object): p = PyObjectPtr(gdbval) cls = cls.subclass_from_type(p.type()) return cls(gdbval, cast_to=cls.get_gdb_type()) - except RuntimeError: + except RuntimeError, exc: # Handle any kind of error e.g. NULL ptrs by simply using the base # class pass @@ -555,19 +559,6 @@ class PyBaseExceptionObjectPtr(PyObjectPtr): out.write(self.safe_tp_name()) self.write_field_repr('args', out, visited) -class PyBoolObjectPtr(PyObjectPtr): - """ - Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two - instances (Py_True/Py_False) within the process being debugged. - """ - _typename = 'PyBoolObject' - - def proxyval(self, visited): - if int_from_int(self.field('ob_ival')): - return True - else: - return False - class PyClassObjectPtr(PyObjectPtr): """ @@ -821,11 +812,10 @@ class PyBoolObjectPtr(PyLongObjectPtr): Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two instances (Py_True/Py_False) within the process being debugged. """ + def proxyval(self, visited): - if PyLongObjectPtr.proxyval(self, visited): - return True - else: - return False + return bool(PyLongObjectPtr.proxyval(self, visited)) + class PyNoneStructPtr(PyObjectPtr): """ @@ -1073,6 +1063,10 @@ class PyBytesObjectPtr(PyObjectPtr): out.write(byte) out.write(quote) +class PyStringObjectPtr(PyBytesObjectPtr): + _typename = 'PyStringObject' + + class PyTupleObjectPtr(PyObjectPtr): _typename = 'PyTupleObject' @@ -1691,7 +1685,8 @@ class PyNameEquals(gdb.Function): pyframe = frame.get_pyop() if pyframe is None: return None - val = str(getattr(pyframe, attr)); print val, val.proxyval(set()); return val + + return str(getattr(pyframe, attr)) return None @@ -1924,8 +1919,14 @@ class GenericCodeStepper(gdb.Command): context. """ - def stopped(self): - return get_selected_inferior().pid == 0 + def stopped(self, result): + match = re.search('^Program received signal .*', result, re.MULTILINE) + if match: + return match.group(0) + elif get_selected_inferior().pid == 0: + return result + else: + return None def _stackdepth(self, frame): depth = 0 @@ -1941,8 +1942,17 @@ class GenericCodeStepper(gdb.Command): of source code or the result of the last executed gdb command (passed in as the `result` argument). """ - if self.stopped(): + result = self.stopped(result) + if result: print result.strip() + # check whether the program was killed by a signal, it should still + # have a stack. + try: + frame = gdb.selected_frame() + except RuntimeError: + pass + else: + print self.get_source_line(frame) else: frame = gdb.selected_frame() output = None @@ -1985,7 +1995,7 @@ class GenericCodeStepper(gdb.Command): hitbp = re.search(r'Breakpoint (\d+)', result) is_relavant = self.is_relevant_function(frame) - if hitbp or is_relavant or self.stopped(): + if hitbp or is_relavant or self.stopped(result): break self.finish_executing(result) @@ -2012,7 +2022,7 @@ class GenericCodeStepper(gdb.Command): else: result = self._finish() - if self.stopped(): + if self.stopped(result): break newframe = gdb.selected_frame() -- 2.26.2