This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
FYI: fix varobj bug with python iterator errors
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Thu, 31 Mar 2011 13:58:45 -0600
- Subject: FYI: fix varobj bug with python iterator errors
I'm checking this in.
A user on irc pointed out that throwing an exception from a
pretty-printer iterator's "next" method would hit the "unhandled Python
exception" case in restore_python_env.
The bug was that the iteration code did not properly handle exceptions
when iterating. This patch fixes the problem and brings varobj in line
with the CLI code regarding handling of gdb.MemoryError.
Built and regtested on x86-64 (compile farm).
New test case included.
Tom
2011-03-31 Tom Tromey <tromey@redhat.com>
* varobj.c (update_dynamic_varobj_children): Properly handle
errors from iterator.
2011-03-31 Tom Tromey <tromey@redhat.com>
* gdb.python/py-prettyprint.py (exception_flag): New global.
(NoStringContainerPrinter._iterator.next): Check it.
* gdb.python/py-prettyprint.c (main): New variable nstype2.
* gdb.python/py-mi.exp: Set exception_flag and do more tests.
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 8aa692d..907fff9 100644
diff --git a/gdb/testsuite/gdb.python/py-mi.exp b/gdb/testsuite/gdb.python/py-mi.exp
index 02763f1..629417b 100644
--- a/gdb/testsuite/gdb.python/py-mi.exp
+++ b/gdb/testsuite/gdb.python/py-mi.exp
@@ -274,4 +274,13 @@ mi_gdb_test "-var-set-visualizer nscont gdb.default_visualizer" \
"\\^done" \
"choose default visualizer"
+mi_gdb_test "python exception_flag = True" ""
+
+mi_create_dynamic_varobj nstype2 nstype2 \
+ "create nstype2 varobj"
+
+mi_list_varobj_children nstype2 {
+ { {nstype2.<error at 0>} {<error at 0>} 6 {char \[6\]} }
+} "list children after setting exception flag"
+
remote_file host delete ${remote_python_file}
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c
index 35c7500..5f98433 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.c
+++ b/gdb/testsuite/gdb.python/py-prettyprint.c
@@ -212,7 +212,7 @@ main ()
const struct string_repr cstring = { { "const string" } };
/* Clearing by being `static' could invoke an other GDB C++ bug. */
struct nullstr nullstr;
- nostring_type nstype;
+ nostring_type nstype, nstype2;
struct ns ns, ns2;
struct lazystring estring, estring2;
@@ -283,5 +283,7 @@ main ()
nstype.elements[1] = 42;
nstype.len = 2;
+ nstype2 = nstype;
+
return 0; /* break to inspect struct and union */
}
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.py b/gdb/testsuite/gdb.python/py-prettyprint.py
index 873039a..831a163 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.py
+++ b/gdb/testsuite/gdb.python/py-prettyprint.py
@@ -53,6 +53,9 @@ class ContainerPrinter:
def children(self):
return self._iterator(self.val['elements'], self.val['len'])
+# Flag to make NoStringContainerPrinter throw an exception.
+exception_flag = False
+
# Test a printer where to_string is None
class NoStringContainerPrinter:
class _iterator:
@@ -67,6 +70,8 @@ class NoStringContainerPrinter:
def next(self):
if self.pointer == self.end:
raise StopIteration
+ if exception_flag:
+ raise gdb.MemoryError, 'hi bob'
result = self.pointer
self.pointer = self.pointer + 1
return ('[%d]' % int (result - self.start), result.dereference())
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 99d8d45..30c2af7 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -1027,6 +1027,7 @@ update_dynamic_varobj_children (struct varobj *var,
for (; to < 0 || i < to + 1; ++i)
{
PyObject *item;
+ int force_done = 0;
/* See if there was a leftover from last time. */
if (var->saved_item)
@@ -1038,7 +1039,48 @@ update_dynamic_varobj_children (struct varobj *var,
item = PyIter_Next (var->child_iter);
if (!item)
- break;
+ {
+ /* Normal end of iteration. */
+ if (!PyErr_Occurred ())
+ break;
+
+ /* If we got a memory error, just use the text as the
+ item. */
+ if (PyErr_ExceptionMatches (gdbpy_gdb_memory_error))
+ {
+ PyObject *type, *value, *trace;
+ char *name_str, *value_str;
+
+ PyErr_Fetch (&type, &value, &trace);
+ value_str = gdbpy_exception_to_string (type, value);
+ Py_XDECREF (type);
+ Py_XDECREF (value);
+ Py_XDECREF (trace);
+ if (!value_str)
+ {
+ gdbpy_print_stack ();
+ break;
+ }
+
+ name_str = xstrprintf ("<error at %d>", i);
+ item = Py_BuildValue ("(ss)", name_str, value_str);
+ xfree (name_str);
+ xfree (value_str);
+ if (!item)
+ {
+ gdbpy_print_stack ();
+ break;
+ }
+
+ force_done = 1;
+ }
+ else
+ {
+ /* Any other kind of error. */
+ gdbpy_print_stack ();
+ break;
+ }
+ }
/* We don't want to push the extra child on any report list. */
if (to < 0 || i < to)
@@ -1052,7 +1094,10 @@ update_dynamic_varobj_children (struct varobj *var,
inner = make_cleanup_py_decref (item);
if (!PyArg_ParseTuple (item, "sO", &name, &py_v))
- error (_("Invalid item from the child list"));
+ {
+ gdbpy_print_stack ();
+ error (_("Invalid item from the child list"));
+ }
v = convert_value_from_python (py_v);
if (v == NULL)
@@ -1072,6 +1117,9 @@ update_dynamic_varobj_children (struct varobj *var,
element. */
break;
}
+
+ if (force_done)
+ break;
}
if (i < VEC_length (varobj_p, var->children))