Choose PyString/PyBytesObjectPtr according to python version + support signals termin...
authormark <mark@eggy.(none)>
Fri, 26 Nov 2010 23:56:18 +0000 (00:56 +0100)
committermark <mark@eggy.(none)>
Fri, 26 Nov 2010 23:56:18 +0000 (00:56 +0100)
Cython/Debugger/Tests/test_libcython_in_gdb.py
Cython/Debugger/libcython.py
Cython/Debugger/libpython.py

index 85a580ffb584cc83d18fa735ec38679f69af7334..7042d96ffb821293c2bfd04df9f773d2e9f1b007 100644 (file)
@@ -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
index d5e17c93b43b4224a8a89781d2721bf1d1fe094d..a6142ab59804a622580859895da2550bafbca551 100644 (file)
@@ -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):
index 653ee21993c9bdfdac40c3be2caaf4b79314ea0b..593cd5803a61fe483d0f1928e97f4db63052679d 100644 (file)
@@ -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
-    <bool> 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
     <bool> 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()