This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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))


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]