Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a backtrace from a SystemStackError: stack level too deep?

Tags:

ruby

Often I get hard to debug infinite recursions when coding ruby. Is there a way to get a backtrace out of a SystemStackError to find out, where exactly the infinite loop occurs?

Example

Given some methods foo, bar and baz which call each other in a loop:

def foo   bar end  def bar   baz end  def baz   foo end  foo 

When I run this code, I just get the message test.rb:6: stack level too deep (SystemStackError). It would be useful to get at least the last 100 lines of the stack, so I could immediately see this is a loop between foo, bar and baz, like this:

test.rb:6: stack level too deep (SystemStackError)   test.rb:2:in `foo'   test.rb:10:in `baz'   test.rb:6:in `bar'   test.rb:2:in `foo'   test.rb:10:in `baz'   test.rb:6:in `bar'   test.rb:2:in `foo'   [...] 

Is there any way to accomplish this?

EDIT:

As you may see from the answer below, Rubinius can do it. Unfortunately some rubinius bugs prevent me from using it with the software I'd like to debug. So to be precise the question is:

How do I get a backtrace with MRI (the default ruby) 1.9?

like image 684
iblue Avatar asked Jul 18 '12 15:07

iblue


People also ask

What does stack level too deep mean?

The stack level too deep error occurs also, if you want to destroy a record and you have an association with :dependent => :destroy to another model. If the other model has a association with :dependent => :destroy back to this model, the stack level is too deep, too.

What is stack trace Ruby?

The stack trace (usually named "backtrace" in Ruby, but also referred to as "stack backtrace" and "stack traceback") is a human-readable representation of the stack at a specific moment while running your program.


1 Answers

Another method for those finding this question later... An excellent gist provides instructions on enabling a trace function in the console and printing all function calls to a file. Just tested on 1.9.3-p194 and it worked great.

Including here in case the gist goes away someday:

$enable_tracing = false $trace_out = open('trace.txt', 'w')  set_trace_func proc { |event, file, line, id, binding, classname|   if $enable_tracing && event == 'call'     $trace_out.puts "#{file}:#{line} #{classname}##{id}"   end }  $enable_tracing = true a_method_that_causes_infinite_recursion_in_a_not_obvious_way() 
like image 185
Elliot Nelson Avatar answered Oct 19 '22 03:10

Elliot Nelson