changeset 19449:972abb60c30f

emit stack trace immediately at point of error * error.cc (pr_where): Get stack trace info in list of frames instead of octave_map. (error_2): Always display stack trace here, not just when entering debug mode. * toplev.h, toplev.cc (octave_call_stack::stack_frame): Rename from octave_call_stack::call_stack_elt. Change all uses. Declare as class instead of struct. Make data privave. (stack_frame::line, stack_frame::column, stack_frame::fcn_file_name, stack_frame::fcn_name): New methods. (octave_call_stack::backtrace): Allow calling with zero or one arg. (octave_call_stack::backtrace_frames, octave_call_stack::do_backtrace_frames): New methods.x (octave_call_stack::backtrace_error_message, octave_call_stack::do_backtrace_error_message): Delete. * ov-oncleanup.cc (octave_oncleanup::~octave_oncleanup): Don't print stack trace here. * ov-usr-fcn.cc (octave_user_script::do_multi_index_op, octave_user_fcn::do_multi_index_op): Don't print stack trace here.
author John W. Eaton <jwe@octave.org>
date Sun, 21 Dec 2014 17:49:28 -0500
parents a2a79462b7b8
children 06b23f224f52
files libinterp/corefcn/error.cc libinterp/corefcn/toplev.cc libinterp/corefcn/toplev.h libinterp/octave-value/ov-oncleanup.cc libinterp/octave-value/ov-usr-fcn.cc
diffstat 5 files changed, 242 insertions(+), 215 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/error.cc	Sun Dec 21 08:09:28 2014 -0800
+++ b/libinterp/corefcn/error.cc	Sun Dec 21 17:49:28 2014 -0500
@@ -422,31 +422,25 @@
 static void
 pr_where (const char *who)
 {
-  octave_idx_type curr_frame = -1;
-
-  octave_map stk = octave_call_stack::backtrace (0, curr_frame);
+  std::list<octave_call_stack::stack_frame> frames
+    = octave_call_stack::backtrace_frames ();
 
-  octave_idx_type nframes_to_display = stk.numel ();
-
-  if (nframes_to_display > 0)
-    {
-      pr_where_1 ("%s: called from\n", who);
+  size_t nframes = frames.size ();
 
-      Cell names = stk.contents ("name");
-      Cell lines = stk.contents ("line");
-      Cell columns = stk.contents ("column");
+  if (nframes > 0)
+    pr_where_1 ("%s: called from\n", who);
+  
+  for (std::list<octave_call_stack::stack_frame>::const_iterator p = frames.begin ();
+       p != frames.end (); p++)
+    {
+      const octave_call_stack::stack_frame& elt = *p;
 
-      for (octave_idx_type i = 0; i < nframes_to_display; i++)
-        {
-          octave_value name = names(i);
-          octave_value line = lines(i);
-          octave_value column = columns(i);
+      std::string fcn_name = elt.fcn_name ();
+      int line = elt.line ();
+      int column = elt.column ();
 
-          std::string nm = name.string_value ();
-
-          pr_where_1 ("    %s at line %d column %d\n", nm.c_str (),
-                      line.int_value (), column.int_value ());
-        }
+      pr_where_1 ("    %s at line %d column %d\n",
+                  fcn_name.c_str (), line, column);
     }
 }
 
@@ -457,6 +451,9 @@
 
   error_1 (std::cerr, "error", id, fmt, args, with_cfn);
 
+  if (! symbol_table::at_top_level () && ! discard_error_messages)
+    pr_where ("error");
+
   if ((interactive || forced_interactive)
       && Vdebug_on_error && init_state == 0
       && octave_call_stack::caller_user_code ())
@@ -467,8 +464,6 @@
 
       error_state = 0;
 
-      pr_where ("error");
-
       tree_evaluator::debug_mode = true;
 
       tree_evaluator::current_frame = octave_call_stack::current_frame ();
--- a/libinterp/corefcn/toplev.cc	Sun Dec 21 08:09:28 2014 -0800
+++ b/libinterp/corefcn/toplev.cc	Sun Dec 21 17:49:28 2014 -0500
@@ -104,6 +104,32 @@
 
 octave_call_stack *octave_call_stack::instance = 0;
 
+std::string
+octave_call_stack::stack_frame::fcn_file_name (void) const
+{
+  return m_fcn ? m_fcn->fcn_file_name () : std::string ();
+}
+
+std::string
+octave_call_stack::stack_frame::fcn_name (bool print_subfn) const
+{
+  std::string retval;
+
+  if (m_fcn)
+    {
+      std::string parent_fcn_name = m_fcn->parent_fcn_name ();
+
+      if (print_subfn && ! parent_fcn_name.empty ())
+        retval = parent_fcn_name + Vfilemarker;
+
+      retval += m_fcn->name ();
+    }
+  else
+    retval = "<unknown>";
+  
+  return retval;
+}
+
 void
 octave_call_stack::create_instance (void)
 {
@@ -124,8 +150,8 @@
 
   if (! cs.empty ())
     {
-      const call_stack_elt& elt = cs[curr_frame];
-      retval = elt.line;
+      const stack_frame& elt = cs[curr_frame];
+      retval = elt.m_line;
     }
 
   return retval;
@@ -138,8 +164,8 @@
 
   if (! cs.empty ())
     {
-      const call_stack_elt& elt = cs[curr_frame];
-      retval = elt.column;
+      const stack_frame& elt = cs[curr_frame];
+      retval = elt.m_column;
     }
 
   return retval;
@@ -154,15 +180,15 @@
 
   while (p != cs.begin ())
     {
-      const call_stack_elt& elt = *(--p);
+      const stack_frame& elt = *(--p);
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
       if (f && f->is_user_code ())
         {
-          if (elt.line > 0)
+          if (elt.m_line > 0)
             {
-              retval = elt.line;
+              retval = elt.m_line;
               break;
             }
         }
@@ -180,15 +206,15 @@
 
   while (p != cs.begin ())
     {
-      const call_stack_elt& elt = *(--p);
+      const stack_frame& elt = *(--p);
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
       if (f && f->is_user_code ())
         {
-          if (elt.column)
+          if (elt.m_column)
             {
-              retval = elt.column;
+              retval = elt.m_column;
               break;
             }
         }
@@ -206,7 +232,7 @@
   curr_user_frame = 0;
 
   // Look for the caller of dbstack.
-  size_t frame = cs[curr_frame].prev;
+  size_t xframe = cs[curr_frame].m_prev;
 
   bool found = false;
 
@@ -214,9 +240,9 @@
 
   for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
     {
-      octave_function *f = (*p).fcn;
+      octave_function *f = (*p).m_fcn;
 
-      if (--k == frame)
+      if (--k == xframe)
         found = true;
 
       if (f && f->is_user_code ())
@@ -244,9 +270,9 @@
 
   while (p != cs.begin ())
     {
-      const call_stack_elt& elt = *(--p);
+      const stack_frame& elt = *(--p);
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
       if (f && f->is_user_code ())
         {
@@ -272,9 +298,9 @@
 
   while (p != cs.begin ())
     {
-      const call_stack_elt& elt = *(--p);
+      const stack_frame& elt = *(--p);
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
       if (f && ! f->is_user_script ())
         {
@@ -299,11 +325,12 @@
   return octave_map (dim_vector (0, 1), bt_fields);
 }
 
-octave_map
-octave_call_stack::do_backtrace (size_t nskip,
-                                 octave_idx_type& curr_user_frame,
-                                 bool print_subfn) const
+std::list<octave_call_stack::stack_frame>
+octave_call_stack::do_backtrace_frames (size_t nskip,
+                                        octave_idx_type& curr_user_frame) const
 {
+  std::list<octave_call_stack::stack_frame> retval;
+
   size_t user_code_frames = do_num_user_code_frames (curr_user_frame);
 
   size_t nframes = nskip <= user_code_frames ? user_code_frames - nskip : 0;
@@ -311,6 +338,37 @@
   // Our list is reversed.
   curr_user_frame = nframes - curr_user_frame - 1;
 
+  if (nframes > 0)
+    {
+      for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
+        {
+          const stack_frame& elt = *p;
+
+          octave_function *f = elt.m_fcn;
+
+          if (f && f->is_user_code ())
+            {
+              if (nskip > 0)
+                nskip--;
+              else
+                retval.push_back (elt);
+            }
+        }
+    }
+
+  return retval;
+}
+
+octave_map
+octave_call_stack::do_backtrace (size_t nskip,
+                                 octave_idx_type& curr_user_frame,
+                                 bool print_subfn) const
+{
+  std::list<octave_call_stack::stack_frame> frames
+    = do_backtrace_frames (nskip, curr_user_frame);
+
+  size_t nframes = frames.size ();
+  
   octave_map retval (dim_vector (nframes, 1), bt_fields);
 
   Cell& file = retval.contents (0);
@@ -320,39 +378,21 @@
   Cell& scope = retval.contents (4);
   Cell& context = retval.contents (5);
 
-  if (nframes > 0)
-    {
-      int k = 0;
+  octave_idx_type k = 0;
 
-      for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
-        {
-          const call_stack_elt& elt = *p;
-
-          octave_function *f = elt.fcn;
+  for (std::list<octave_call_stack::stack_frame>::const_iterator p = frames.begin ();
+       p != frames.end (); p++)
+    {
+      const stack_frame& elt = *p;
 
-          if (f && f->is_user_code ())
-            {
-              if (nskip > 0)
-                nskip--;
-              else
-                {
-                  scope(k) = elt.scope;
-                  context(k) = elt.context;
+      scope(k) = elt.m_scope;
+      context(k) = elt.m_context;
+      file(k) = elt.fcn_file_name ();
+      name(k) = elt.fcn_name (print_subfn);
+      line(k) = elt.m_line;
+      column(k) = elt.m_column;
 
-                  file(k) = f->fcn_file_name ();
-                  std::string parent_fcn_name = f->parent_fcn_name ();
-                  if (! print_subfn || parent_fcn_name == std::string ())
-                    name(k) = f->name ();
-                  else
-                    name(k) = f->parent_fcn_name () + Vfilemarker + f->name ();
-
-                  line(k) = elt.line;
-                  column(k) = elt.column;
-
-                  k++;
-                }
-            }
-        }
+      k++;
     }
 
   return retval;
@@ -369,21 +409,16 @@
 
       curr_frame = n;
 
-      const call_stack_elt& elt = cs[n];
+      const stack_frame& elt = cs[n];
 
-      symbol_table::set_scope_and_context (elt.scope, elt.context);
+      symbol_table::set_scope_and_context (elt.m_scope, elt.m_context);
 
       if (verbose)
-        {
-          octave_function *f = elt.fcn;
-          std::string nm = f ? f->name () : std::string ("<unknown>");
-
-          octave_stdout << "stopped in " << nm
-                        << " at line " << elt.line
-                        << " column " << elt.column
-                        << " (" << elt.scope << "[" << elt.context << "])"
-                        << std::endl;
-        }
+        octave_stdout << "stopped in " << elt.fcn_name ()
+                      << " at line " << elt.m_line
+                      << " column " << elt.m_column
+                      << " (" << elt.m_scope << "[" << elt.m_context << "])"
+                      << std::endl;
     }
 
   return retval;
@@ -402,20 +437,20 @@
     incr = 1;
 
   // Start looking with the caller of dbup/dbdown/keyboard.
-  size_t frame = cs[curr_frame].prev;
+  size_t xframe = cs[curr_frame].m_prev;
 
   while (true)
     {
-      if ((incr < 0 && frame == 0) || (incr > 0 && frame == cs.size () - 1))
+      if ((incr < 0 && xframe == 0) || (incr > 0 && xframe == cs.size () - 1))
         break;
 
-      frame += incr;
+      xframe += incr;
 
-      const call_stack_elt& elt = cs[frame];
+      const stack_frame& elt = cs[xframe];
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
-      if (frame == 0 || (f && f->is_user_code ()))
+      if (xframe == 0 || (f && f->is_user_code ()))
         {
           if (nskip > 0)
             nskip--;
@@ -424,10 +459,10 @@
 
           if (nskip == 0)
             {
-              curr_frame = frame;
-              cs[cs.size () - 1].prev = curr_frame;
+              curr_frame = xframe;
+              cs[cs.size () - 1].m_prev = curr_frame;
 
-              symbol_table::set_scope_and_context (elt.scope, elt.context);
+              symbol_table::set_scope_and_context (elt.m_scope, elt.m_context);
 
               if (verbose)
                 {
@@ -435,7 +470,7 @@
 
                   if (f)
                     buf << "stopped in " << f->name ()
-                        << " at line " << elt.line << std::endl;
+                        << " at line " << elt.m_line << std::endl;
                   else
                     buf << "at top level" << std::endl;
 
@@ -460,19 +495,19 @@
 void
 octave_call_stack::do_goto_caller_frame (void)
 {
-  size_t frame = curr_frame;
+  size_t xframe = curr_frame;
 
   bool skipped = false;
 
-  while (frame != 0)
+  while (xframe != 0)
     {
-      frame = cs[frame].prev;
+      xframe = cs[xframe].m_prev;
 
-      const call_stack_elt& elt = cs[frame];
+      const stack_frame& elt = cs[xframe];
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
-      if (elt.scope == cs[0].scope || (f && f->is_user_code ()))
+      if (elt.m_scope == cs[0].m_scope || (f && f->is_user_code ()))
         {
           if (! skipped)
             // We found the current user code frame, so skip it.
@@ -480,14 +515,14 @@
           else
             {
               // We found the caller user code frame.
-              call_stack_elt tmp (elt);
-              tmp.prev = curr_frame;
+              stack_frame tmp (elt);
+              tmp.m_prev = curr_frame;
 
               curr_frame = cs.size ();
 
               cs.push_back (tmp);
 
-              symbol_table::set_scope_and_context (tmp.scope, tmp.context);
+              symbol_table::set_scope_and_context (tmp.m_scope, tmp.m_context);
 
               break;
             }
@@ -498,45 +533,14 @@
 void
 octave_call_stack::do_goto_base_frame (void)
 {
-  call_stack_elt tmp (cs[0]);
-  tmp.prev = curr_frame;
+  stack_frame tmp (cs[0]);
+  tmp.m_prev = curr_frame;
 
   curr_frame = cs.size ();
 
   cs.push_back (tmp);
 
-  symbol_table::set_scope_and_context (tmp.scope, tmp.context);
-}
-
-void
-octave_call_stack::do_backtrace_error_message (void) const
-{
-  if (error_state > 0)
-    {
-      error_state = -1;
-
-      error ("called from:");
-    }
-
-  if (! cs.empty ())
-    {
-      const call_stack_elt& elt = cs.back ();
-
-      octave_function *fcn = elt.fcn;
-
-      std::string fcn_name = "?unknown?";
-
-      if (fcn)
-        {
-          fcn_name = fcn->fcn_file_name ();
-
-          if (fcn_name.empty ())
-            fcn_name = fcn->name ();
-        }
-
-      error ("  %s at line %d, column %d",
-             fcn_name.c_str (), elt.line, elt.column);
-    }
+  symbol_table::set_scope_and_context (tmp.m_scope, tmp.m_context);
 }
 
 void
--- a/libinterp/corefcn/toplev.h	Sun Dec 21 08:09:28 2014 -0800
+++ b/libinterp/corefcn/toplev.h	Sun Dec 21 17:49:28 2014 -0500
@@ -76,41 +76,52 @@
 OCTINTERP_API
 octave_call_stack
 {
-private:
-
-  struct call_stack_elt
-  {
-    call_stack_elt (octave_function *f, symbol_table::scope_id s,
-                    symbol_table::context_id c, size_t p = 0)
-      : fcn (f), line (-1), column (-1), scope (s), context (c), prev (p)
-    { }
-
-    call_stack_elt (const call_stack_elt& elt)
-      : fcn (elt.fcn), line (elt.line), column (elt.column),
-        scope (elt.scope), context (elt.context), prev (elt.prev)
-    { }
-
-    octave_function *fcn;
-    int line;
-    int column;
-    symbol_table::scope_id scope;
-    symbol_table::context_id context;
-    size_t prev;
-  };
-
 protected:
 
   octave_call_stack (void) : cs (), curr_frame (0) { }
 
 public:
 
-  typedef std::deque<call_stack_elt>::iterator iterator;
-  typedef std::deque<call_stack_elt>::const_iterator const_iterator;
+  class stack_frame
+  {
+  public:
+
+    friend class octave_call_stack;
+
+    stack_frame (octave_function *fcn = 0, symbol_table::scope_id scope = 0,
+                 symbol_table::context_id context = 0, size_t prev = 0)
+      : m_fcn (fcn), m_line (-1), m_column (-1), m_scope (scope),
+        m_context (context), m_prev (prev)
+    { }
+
+    stack_frame (const stack_frame& elt)
+      : m_fcn (elt.m_fcn), m_line (elt.m_line), m_column (elt.m_column),
+        m_scope (elt.m_scope), m_context (elt.m_context), m_prev (elt.m_prev)
+    { }
+
+    int line (void) const { return m_line; }
 
-  typedef std::deque<call_stack_elt>::reverse_iterator
-    reverse_iterator;
-  typedef std::deque<call_stack_elt>::const_reverse_iterator
-    const_reverse_iterator;
+    int column (void) const { return m_column; }
+
+    std::string fcn_file_name (void) const;
+
+    std::string fcn_name (bool print_subfn = true) const;
+
+  private:
+
+    octave_function *m_fcn;
+    int m_line;
+    int m_column;
+    symbol_table::scope_id m_scope;
+    symbol_table::context_id m_context;
+    size_t m_prev;
+  };
+
+  typedef std::deque<stack_frame>::iterator iterator;
+  typedef std::deque<stack_frame>::const_iterator const_iterator;
+
+  typedef std::deque<stack_frame>::reverse_iterator reverse_iterator;
+  typedef std::deque<stack_frame>::const_reverse_iterator const_reverse_iterator;
 
   static void create_instance (void);
 
@@ -193,6 +204,12 @@
     return instance_ok () ? instance->do_current_context () : 0;
   }
 
+  /*
+  static stack_frame frame (size_t idx)
+  {
+    return instance_ok () ? instance->do_frame (idx) : stack_frame ();
+  }
+  */
   // Function at location N on the call stack (N == 0 is current), may
   // be built-in.
   static octave_function *element (size_t n)
@@ -275,21 +292,41 @@
       instance->do_goto_base_frame ();
   }
 
-  static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame)
+  static octave_map backtrace (size_t nskip = 0)
   {
+    octave_idx_type curr_user_frame = -1;
+
     return instance_ok ()
            ? instance->do_backtrace (nskip, curr_user_frame, true)
            : octave_map ();
   }
-
+  
   static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame,
-                               bool print_subfn)
+                               bool print_subfn = true)
   {
     return instance_ok ()
            ? instance->do_backtrace (nskip, curr_user_frame, print_subfn)
            : octave_map ();
   }
 
+  static std::list<octave_call_stack::stack_frame>
+  backtrace_frames (size_t nskip = 0)
+  {
+    octave_idx_type curr_user_frame = -1;
+
+    return instance_ok ()
+           ? instance->do_backtrace_frames (nskip, curr_user_frame)
+           : std::list<octave_call_stack::stack_frame> ();
+  }
+  
+  static std::list<octave_call_stack::stack_frame>
+  backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame)
+  {
+    return instance_ok ()
+           ? instance->do_backtrace_frames (nskip, curr_user_frame)
+           : std::list<octave_call_stack::stack_frame> ();
+  }
+
   static octave_map empty_backtrace (void);
 
   static void pop (void)
@@ -304,16 +341,10 @@
       instance->do_clear ();
   }
 
-  static void backtrace_error_message (void)
-  {
-    if (instance_ok ())
-      instance->do_backtrace_error_message ();
-  }
-
 private:
 
   // The current call stack.
-  std::deque<call_stack_elt> cs;
+  std::deque<stack_frame> cs;
 
   size_t curr_frame;
 
@@ -331,7 +362,7 @@
 
   octave_function *do_caller (void) const
   {
-    return curr_frame > 1 ? cs[curr_frame-1].fcn : cs[0].fcn;
+    return curr_frame > 1 ? cs[curr_frame-1].m_fcn : cs[0].m_fcn;
   }
 
   size_t do_current_frame (void) { return curr_frame; }
@@ -343,23 +374,30 @@
   symbol_table::scope_id do_current_scope (void) const
   {
     return curr_frame > 0 && curr_frame < cs.size ()
-           ? cs[curr_frame].scope : 0;
+           ? cs[curr_frame].m_scope : 0;
   }
 
   symbol_table::context_id do_current_context (void) const
   {
     return curr_frame > 0 && curr_frame < cs.size ()
-           ? cs[curr_frame].context : 0;
+           ? cs[curr_frame].m_context : 0;
   }
 
+  /*  const stack_frame& do_frame (size_t idx)
+  {
+    static stack_frame foobar;
+
+    return idx < cs.size () ? cs[idx] : foobar;
+  }
+  */
   octave_function *do_element (size_t n)
   {
     octave_function *retval = 0;
 
     if (cs.size () > n)
       {
-        call_stack_elt& elt = cs[n];
-        retval = elt.fcn;
+        stack_frame& elt = cs[n];
+        retval = elt.m_fcn;
       }
 
     return retval;
@@ -369,12 +407,12 @@
 
   bool do_all_scripts (void) const;
 
-  void do_push (octave_function *f, symbol_table::scope_id scope,
+  void do_push (octave_function *fcn, symbol_table::scope_id scope,
                 symbol_table::context_id context)
   {
     size_t prev_frame = curr_frame;
     curr_frame = cs.size ();
-    cs.push_back (call_stack_elt (f, scope, context, prev_frame));
+    cs.push_back (stack_frame (fcn, scope, context, prev_frame));
     symbol_table::set_scope_and_context (scope, context);
   }
 
@@ -384,8 +422,8 @@
 
     if (! cs.empty ())
       {
-        const call_stack_elt& elt = cs[curr_frame];
-        retval = elt.fcn;
+        const stack_frame& elt = cs[curr_frame];
+        retval = elt.m_fcn;
       }
 
     return retval;
@@ -395,10 +433,10 @@
   {
     if (! cs.empty ())
       {
-        call_stack_elt& elt = cs.back ();
+        stack_frame& elt = cs.back ();
 
-        elt.line = l;
-        elt.column = c;
+        elt.m_line = l;
+        elt.m_column = c;
       }
   }
 
@@ -406,9 +444,9 @@
   {
     if (! cs.empty ())
       {
-        call_stack_elt& elt = cs.back ();
+        stack_frame& elt = cs.back ();
 
-        elt.line = l;
+        elt.m_line = l;
       }
   }
 
@@ -416,12 +454,15 @@
   {
     if (! cs.empty ())
       {
-        call_stack_elt& elt = cs.back ();
+        stack_frame& elt = cs.back ();
 
-        elt.column = c;
+        elt.m_column = c;
       }
   }
 
+  std::list<octave_call_stack::stack_frame>
+  do_backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) const;
+
   octave_map do_backtrace (size_t nskip,
                            octave_idx_type& curr_user_frame,
                            bool print_subfn) const;
@@ -438,17 +479,15 @@
   {
     if (cs.size () > 1)
       {
-        const call_stack_elt& elt = cs.back ();
-        curr_frame = elt.prev;
+        const stack_frame& elt = cs.back ();
+        curr_frame = elt.m_prev;
         cs.pop_back ();
-        const call_stack_elt& new_elt = cs[curr_frame];
-        symbol_table::set_scope_and_context (new_elt.scope, new_elt.context);
+        const stack_frame& new_elt = cs[curr_frame];
+        symbol_table::set_scope_and_context (new_elt.m_scope, new_elt.m_context);
       }
   }
 
   void do_clear (void) { cs.clear (); }
-
-  void do_backtrace_error_message (void) const;
 };
 
 // Call a function with exceptions handled to avoid problems with
--- a/libinterp/octave-value/ov-oncleanup.cc	Sun Dec 21 08:09:28 2014 -0800
+++ b/libinterp/octave-value/ov-oncleanup.cc	Sun Dec 21 17:49:28 2014 -0500
@@ -98,14 +98,9 @@
       error ("onCleanup: internal error: unhandled exception in cleanup action");
     }
 
-  // We don't want to ignore errors that occur in the cleanup code, so
-  // if an error is encountered there, leave error_state alone.
-  // Otherwise, set it back to what it was before.
+  // FIXME: can this happen now?
   if (error_state)
-    {
-      frame.discard_first ();
-      octave_call_stack::backtrace_error_message ();
-    }
+    frame.discard_first ();
 }
 
 octave_scalar_map
--- a/libinterp/octave-value/ov-usr-fcn.cc	Sun Dec 21 08:09:28 2014 -0800
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Sun Dec 21 17:49:28 2014 -0500
@@ -160,9 +160,6 @@
 
                   if (tree_break_command::breaking)
                     tree_break_command::breaking--;
-
-                  if (error_state)
-                    octave_call_stack::backtrace_error_message ();
                 }
               else
                 ::error ("max_recursion_depth exceeded");
@@ -642,10 +639,7 @@
     tree_break_command::breaking--;
 
   if (error_state)
-    {
-      octave_call_stack::backtrace_error_message ();
-      return retval;
-    }
+    return retval;
 
   // Copy return values out.