If a frame level has been printed, do not print it again (in the
     case of elided frames).  Returns EXT_LANG_BT_ERROR on error, with any
     GDB exceptions converted to a Python exception, or EXT_LANG_BT_COMPLETED
-    on success.  */
+    on success.  It can also throw an exception RETURN_QUIT.  */
 
 static enum ext_lang_bt_status
 py_print_frame (PyObject *filter, int flags,
   CORE_ADDR address = 0;
   struct gdbarch *gdbarch = NULL;
   struct frame_info *frame = NULL;
-  struct cleanup *cleanup_stack = make_cleanup (null_cleanup, NULL);
+  struct cleanup *cleanup_stack;
   struct value_print_options opts;
   PyObject *py_inf_frame;
   int print_level, print_frame_info, print_args, print_locals;
   read them if they returned filter object requires us to do so.  */
   py_inf_frame = PyObject_CallMethod (filter, "inferior_frame", NULL);
   if (py_inf_frame == NULL)
-    {
-      do_cleanups (cleanup_stack);
-      return EXT_LANG_BT_ERROR;
-    }
+    return EXT_LANG_BT_ERROR;
 
   frame = frame_object_to_frame_info (py_inf_frame);;
 
   Py_DECREF (py_inf_frame);
 
   if (frame == NULL)
-    {
-      do_cleanups (cleanup_stack);
-      return EXT_LANG_BT_ERROR;
-    }
+    return EXT_LANG_BT_ERROR;
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
   if (except.reason < 0)
     {
       gdbpy_convert_exception (except);
-      do_cleanups (cleanup_stack);
       return EXT_LANG_BT_ERROR;
     }
 
     {
       if (py_mi_print_variables (filter, out, &opts,
                                 args_type, frame) == EXT_LANG_BT_ERROR)
-       {
-         do_cleanups (cleanup_stack);
-         return EXT_LANG_BT_ERROR;
-       }
-      do_cleanups (cleanup_stack);
+       return EXT_LANG_BT_ERROR;
       return EXT_LANG_BT_COMPLETED;
     }
 
+  cleanup_stack = make_cleanup (null_cleanup, NULL);
+
   /* -stack-list-locals does not require a
      wrapping frame attribute.  */
   if (print_frame_info || (print_args && ! print_locals))
       if (PyObject_HasAttrString (filter, "function"))
        {
          PyObject *py_func = PyObject_CallMethod (filter, "function", NULL);
+         struct cleanup *py_func_cleanup;
          const char *function = NULL;
 
          if (py_func == NULL)
              do_cleanups (cleanup_stack);
              return EXT_LANG_BT_ERROR;
            }
+         py_func_cleanup = make_cleanup_py_decref (py_func);
 
          if (gdbpy_is_string (py_func))
            {
 
              if (function == NULL)
                {
-                 Py_DECREF (py_func);
                  do_cleanups (cleanup_stack);
                  return EXT_LANG_BT_ERROR;
                }
              PyErr_SetString (PyExc_RuntimeError,
                               _("FrameDecorator.function: expecting a " \
                                 "String, integer or None."));
-             Py_DECREF (py_func);
              do_cleanups (cleanup_stack);
              return EXT_LANG_BT_ERROR;
            }
            }
          if (except.reason < 0)
            {
-             Py_DECREF (py_func);
              gdbpy_convert_exception (except);
              do_cleanups (cleanup_stack);
              return EXT_LANG_BT_ERROR;
            }
-         Py_DECREF (py_func);
+         do_cleanups (py_func_cleanup);
        }
     }
 
       if (PyObject_HasAttrString (filter, "filename"))
        {
          PyObject *py_fn = PyObject_CallMethod (filter, "filename", NULL);
+         struct cleanup *py_fn_cleanup;
 
          if (py_fn == NULL)
            {
              do_cleanups (cleanup_stack);
              return EXT_LANG_BT_ERROR;
            }
+         py_fn_cleanup = make_cleanup_py_decref (py_fn);
 
          if (py_fn != Py_None)
            {
 
              if (filename == NULL)
                {
-                 Py_DECREF (py_fn);
                  do_cleanups (cleanup_stack);
                  return EXT_LANG_BT_ERROR;
                }
                }
              if (except.reason < 0)
                {
-                 Py_DECREF (py_fn);
                  gdbpy_convert_exception (except);
                  do_cleanups (cleanup_stack);
                  return EXT_LANG_BT_ERROR;
                }
            }
-         Py_DECREF (py_fn);
+         do_cleanups (py_fn_cleanup);
        }
 
       if (PyObject_HasAttrString (filter, "line"))
        {
          PyObject *py_line = PyObject_CallMethod (filter, "line", NULL);
+         struct cleanup *py_line_cleanup;
          int line;
 
          if (py_line == NULL)
              do_cleanups (cleanup_stack);
              return EXT_LANG_BT_ERROR;
            }
+         py_line_cleanup = make_cleanup_py_decref (py_line);
 
          if (py_line != Py_None)
            {
                }
              if (except.reason < 0)
                {
-                 Py_DECREF (py_line);
                  gdbpy_convert_exception (except);
                  do_cleanups (cleanup_stack);
                  return EXT_LANG_BT_ERROR;
                }
            }
-         Py_DECREF (py_line);
+         do_cleanups (py_line_cleanup);
        }
     }
 
 
   {
     PyObject *elided;
+    struct cleanup *elided_cleanup;
 
     /* Finally recursively print elided frames, if any.  */
     elided = get_py_iter_from_func (filter, "elided");
        do_cleanups (cleanup_stack);
        return EXT_LANG_BT_ERROR;
       }
+    elided_cleanup = make_cleanup_py_decref (elided);
 
-    make_cleanup_py_decref (elided);
     if (elided != Py_None)
       {
        PyObject *item;
 
        while ((item = PyIter_Next (elided)))
          {
+           struct cleanup *item_cleanup = make_cleanup_py_decref (item);
+
            enum ext_lang_bt_status success = py_print_frame (item, flags,
                                                              args_type, out,
                                                              indent,
                                                              levels_printed);
 
+           do_cleanups (item_cleanup);
+
            if (success == EXT_LANG_BT_ERROR)
              {
-               Py_DECREF (item);
                do_cleanups (cleanup_stack);
                return EXT_LANG_BT_ERROR;
              }
-
-           Py_DECREF (item);
          }
        if (item == NULL && PyErr_Occurred ())
          {
            return EXT_LANG_BT_ERROR;
          }
       }
-    }
-
+    do_cleanups (elided_cleanup);
+  }
 
   do_cleanups (cleanup_stack);
   return EXT_LANG_BT_COMPLETED;
 
   while ((item = PyIter_Next (iterable)))
     {
+      struct cleanup *item_cleanup = make_cleanup_py_decref (item);
+
       success = py_print_frame (item, flags, args_type, out, 0,
                                levels_printed);
 
+      do_cleanups (item_cleanup);
+
       /* Do not exit on error printing a single frame.  Print the
         error and continue with other frames.  */
       if (success == EXT_LANG_BT_ERROR)
        gdbpy_print_stack ();
-
-      Py_DECREF (item);
     }
 
   if (item == NULL && PyErr_Occurred ())