+2018-09-23  Tom Tromey  <tom@tromey.com>
+
+       * python/py-function.c (fnpy_call): Use gdbpy_handle_exception.
+       * python/py-cmd.c (cmdpy_function): Use gdbpy_handle_exception.
+       * python/python-internal.h (gdbpy_handle_exception): Declare.
+       * python/py-utils.c (gdbpy_handle_exception): New function.
+
 2018-09-23  Tom Tromey  <tom@tromey.com>
 
        PR python/17284:
 
                                                  NULL));
 
   if (result == NULL)
-    {
-      PyObject *ptype, *pvalue, *ptraceback;
-
-      PyErr_Fetch (&ptype, &pvalue, &ptraceback);
-
-      /* Try to fetch an error message contained within ptype, pvalue.
-        When fetching the error message we need to make our own copy,
-        we no longer own ptype, pvalue after the call to PyErr_Restore.  */
-
-      gdb::unique_xmalloc_ptr<char>
-       msg (gdbpy_exception_to_string (ptype, pvalue));
-
-      if (msg == NULL)
-       {
-         /* An error occurred computing the string representation of the
-            error message.  This is rare, but we should inform the user.  */
-         printf_filtered (_("An error occurred in a Python command\n"
-                            "and then another occurred computing the "
-                            "error message.\n"));
-         gdbpy_print_stack ();
-       }
-
-      /* Don't print the stack for gdb.GdbError exceptions.
-        It is generally used to flag user errors.
-
-        We also don't want to print "Error occurred in Python command"
-        for user errors.  However, a missing message for gdb.GdbError
-        exceptions is arguably a bug, so we flag it as such.  */
-
-      if (! PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc)
-         || msg == NULL || *msg == '\0')
-       {
-         PyErr_Restore (ptype, pvalue, ptraceback);
-         gdbpy_print_stack ();
-         if (msg != NULL && *msg != '\0')
-           error (_("Error occurred in Python command: %s"), msg.get ());
-         else
-           error (_("Error occurred in Python command."));
-       }
-      else
-       {
-         Py_XDECREF (ptype);
-         Py_XDECREF (pvalue);
-         Py_XDECREF (ptraceback);
-         error ("%s", msg.get ());
-       }
-    }
+    gdbpy_handle_exception ();
 }
 
 /* Helper function for the Python command completers (both "pure"
 
     }
 
   if (result == NULL)
-    {
-      PyObject *ptype, *pvalue, *ptraceback;
-
-      PyErr_Fetch (&ptype, &pvalue, &ptraceback);
-
-      /* Try to fetch an error message contained within ptype, pvalue.
-        When fetching the error message we need to make our own copy,
-        we no longer own ptype, pvalue after the call to PyErr_Restore.  */
-
-      gdb::unique_xmalloc_ptr<char>
-       msg (gdbpy_exception_to_string (ptype, pvalue));
-
-      if (msg == NULL)
-       {
-         /* An error occurred computing the string representation of the
-            error message.  This is rare, but we should inform the user.  */
-
-         printf_filtered (_("An error occurred in a Python "
-                            "convenience function\n"
-                            "and then another occurred computing the "
-                            "error message.\n"));
-         gdbpy_print_stack ();
-       }
-
-      /* Don't print the stack for gdb.GdbError exceptions.
-        It is generally used to flag user errors.
-
-        We also don't want to print "Error occurred in Python command"
-        for user errors.  However, a missing message for gdb.GdbError
-        exceptions is arguably a bug, so we flag it as such.  */
-
-      if (!PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc)
-         || msg == NULL || *msg == '\0')
-       {
-         PyErr_Restore (ptype, pvalue, ptraceback);
-         gdbpy_print_stack ();
-         if (msg != NULL && *msg != '\0')
-           error (_("Error occurred in Python convenience function: %s"),
-                  msg.get ());
-         else
-           error (_("Error occurred in Python convenience function."));
-       }
-      else
-       {
-         Py_XDECREF (ptype);
-         Py_XDECREF (pvalue);
-         Py_XDECREF (ptraceback);
-         error ("%s", msg.get ());
-       }
-    }
+    gdbpy_handle_exception ();
 
   value = convert_value_from_python (result.get ());
   if (value == NULL)
 
     Py_DECREF (object);
   return result;
 }
+
+/* Handle a Python exception when the special gdb.GdbError treatment
+   is desired.  This should only be called when an exception is set.
+   If the exception is a gdb.GdbError, throw a gdb exception with the
+   exception text.  For other exceptions, print the Python stack and
+   then throw a gdb exception.  */
+
+void
+gdbpy_handle_exception ()
+{
+  PyObject *ptype, *pvalue, *ptraceback;
+
+  PyErr_Fetch (&ptype, &pvalue, &ptraceback);
+
+  /* Try to fetch an error message contained within ptype, pvalue.
+     When fetching the error message we need to make our own copy,
+     we no longer own ptype, pvalue after the call to PyErr_Restore.  */
+
+  gdb::unique_xmalloc_ptr<char>
+    msg (gdbpy_exception_to_string (ptype, pvalue));
+
+  if (msg == NULL)
+    {
+      /* An error occurred computing the string representation of the
+        error message.  This is rare, but we should inform the user.  */
+      printf_filtered (_("An error occurred in Python "
+                        "and then another occurred computing the "
+                        "error message.\n"));
+      gdbpy_print_stack ();
+    }
+
+  /* Don't print the stack for gdb.GdbError exceptions.
+     It is generally used to flag user errors.
+
+     We also don't want to print "Error occurred in Python command"
+     for user errors.  However, a missing message for gdb.GdbError
+     exceptions is arguably a bug, so we flag it as such.  */
+
+  if (! PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc)
+      || msg == NULL || *msg == '\0')
+    {
+      PyErr_Restore (ptype, pvalue, ptraceback);
+      gdbpy_print_stack ();
+      if (msg != NULL && *msg != '\0')
+       error (_("Error occurred in Python: %s"), msg.get ());
+      else
+       error (_("Error occurred in Python."));
+    }
+  else
+    {
+      Py_XDECREF (ptype);
+      Py_XDECREF (pvalue);
+      Py_XDECREF (ptraceback);
+      error ("%s", msg.get ());
+    }
+}
 
 
 int gdbpy_print_python_errors_p (void);
 void gdbpy_print_stack (void);
+void gdbpy_handle_exception () ATTRIBUTE_NORETURN;
 
 PyObject *python_string_to_unicode (PyObject *obj);
 gdb::unique_xmalloc_ptr<char> unicode_to_target_string (PyObject *unicode_str);