[ANN] breakpoint.rb -- now with remote debugging

F

Florian Gross

Moin!

Breakpoint.rb is a small library that lets you set breakpoints by
calling a method. When executed, a breakpoint causes an interactive ruby
session to be spawned with the current context. This makes it especially
useful for debugging because Ruby has powerful built-in capabilities for
exploring object environments. (Kernel#caller, Object#inspect,
Object#respond_to?, Kernel#local_variables, Object#instance_variables
and so on.)

There's also support for overriding return values and for an assert()
method that automatically sets a breakpoint in case an unexpected
situation occurs.

---

This new version includes support for remote debugging via DRb. Using
this you can now also debug your CGI and Rails applications (and other
applications where you can't pollute STDIN/STDOUT by running irb
directly). To start the DRb breakpoint service you will have to call
Breakpoint.activate_drb -- after that you can interact with that service
by running breakpoint_client.rb.

This is a pre-release of the next version of the code already included
in the Ruby dev-utils project (http://dev-utils.rubyforge.org/) meaning
that I'm not sure if it is 100% bug-free (I refactored quite a lot) --
if this works out well the dev-utils version can be updated.

If you have any suggestions or if you find any problems with this please
mention them now so that I can fix them as soon as possible. Thanks!

Kind regards,
Florian Gross

begin
require 'simplecc'
rescue LoadError
def Continuation.create(*args, &block)
cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?}
result ||= args
return *[cc, *result]
end
end

# This method returns the binding of the method that called your
# method. It will raise an Exception when you're not inside a method.
#
# It's used like this:
# def inc_counter(amount = 1)
# Binding.of_caller do |binding|
# # Create a lambda that will increase the variable 'counter'
# # in the caller of this method when called.
# inc = eval("lambda { |arg| counter += arg }", binding)
# # We can refer to amount from inside this block safely.
# inc.call(amount)
# end
# # No other statements can go here. Put them inside the block.
# end
# counter = 0
# 2.times { inc_counter }
# counter # => 2
#
# Binding.of_caller must be the last statement in the method.
# This means that you will have to put everything you want to
# do after the call to Binding.of_caller into the block of it.
# This should be no problem however, because Ruby has closures.
# If you don't do this an Exception will be raised. Because of
# the way that Binding.of_caller is implemented it has to be
# done this way.
def Binding.of_caller(&block)
old_critical = Thread.critical
Thread.critical = true
count = 0
cc, result, error, extra_data = Continuation.create(nil, nil)
error.call if error

tracer = lambda do |*args|
type, context, extra_data = args[0], args[4], args
if type == "return"
count += 1
# First this method and then calling one will return --
# the trace event of the second event gets the context
# of the method which called the method that called this
# method.
if count == 2
# It would be nice if we could restore the trace_func
# that was set before we swapped in our own one, but
# this is impossible without overloading set_trace_func
# in current Ruby.
set_trace_func(nil)
cc.call(eval("binding", context), nil, extra_data)
end
elsif type != "line"
set_trace_func(nil)
error_msg = "Binding.of_caller used in non-method context or " +
"trailing statements of method using it aren't in the block."
cc.call(nil, lambda { raise(ArgumentError, error_msg) }, nil)
end
end

unless result
set_trace_func(tracer)
return nil
else
Thread.critical = old_critical
case block.arity
when 1 then yield(result)
else yield(result, extra_data)
end
end
end

require 'irb'
require 'binding_of_caller'
require 'drb'

module Breakpoint
extend self

# This will pop up an interactive ruby session at a
# pre-defined break point in a Ruby application. In
# this session you can examine the environment of
# the break point.
#
# You can get a list of variables in the context using
# local_variables via +local_variables+. You can then
# examine their values by typing their names.
#
# You can have a look at the call stack via +caller+.
#
# breakpoints can also return a value. They will execute
# a supplied block for getting a default return value.
# A custom value can be returned from the session by doing
# +throw:)debug_return, value)+.
#
# You can also give names to break points which will be
# used in the message that is displayed upon execution
# of them.
#
# Here's a sample of how breakpoints should be placed:
#
# class Person
# def initialize(name, age)
# @name, @age = name, age
# breakpoint("Person#initialize")
# end
#
# attr_reader :age
# def name
# breakpoint("Person#name") { @name }
# end
# end
#
# person = Person.new("Random Person", 23)
# puts "Name: #{person.name}"
#
# And here is a sample debug session:
#
# Executing break point "Person#initialize" at file.rb:4 in `initialize'
# irb(#<Person:0x292fbe8>):001:0> local_variables
# => ["name", "age", "_", "__"]
# irb(#<Person:0x292fbe8>):002:0> [name, age]
# => ["Random Person", 23]
# irb(#<Person:0x292fbe8>):003:0> [@name, @age]
# => ["Random Person", 23]
# irb(#<Person:0x292fbe8>):004:0> self
# => #<Person:0x292fbe8 @age=23, @name="Random Person">
# irb(#<Person:0x292fbe8>):005:0> @age += 1; self
# => #<Person:0x292fbe8 @age=24, @name="Random Person">
# irb(#<Person:0x292fbe8>):006:0> exit
# Executing break point "Person#name" at file.rb:9 in `name'
# irb(#<Person:0x292fbe8>):001:0> throw:)debug_return, "Overriden name")
# Name: Overriden name
def breakpoint(id = nil, context = nil, &block)
callstack = caller
callstack.slice!(0, 3) if callstack.first["breakpoint"]
file, line, method = *callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures

message = "Executing break point " + (id ? "#{id.inspect} " : "") +
"at #{file}:#{line}" + (method ? " in `#{method}'" : "")

if context then
return handle_breakpoint(context, message, &block)
end

Binding.of_caller do |binding_context|
handle_breakpoint(binding_context, message, &block)
end
end

def handle_breakpoint(context, message, &block) # :nodoc:
catch:)debug_return) do |value|
if not use_drb? then
puts message
IRB.start(nil, IRB::WorkSpace.new(context))
else
@drb_service.add_breakpoint(context, message)
end

block.call if block
end
end
private :handle_breakpoint

# This asserts that the block evaluates to true.
# If it doesn't evaluate to true a breakpoint will
# automatically be created at that execution point.
#
# You can disable assert checking by setting
# Breakpoint.optimize_asserts to true before
# loading the breakpoint.rb library. (It will still
# be enabled when Ruby is run via the -d argument.)
#
# Example:
# person_name = "Foobar"
# assert { not person_name.nil? }
def assert(context = nil, &condition)
return if Breakpoint.optimize_asserts and not $DEBUG
return if yield

callstack = caller
callstack.slice!(0, 3) if callstack.first["assert"]
file, line, method = *callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures

message = "Assert failed at #{file}:#{line}#{" in `#{method}'" if method}. " +
"Executing implicit breakpoint."

if context then
return handle_breakpoint(context, message)
end

Binding.of_caller do |context|
handle_breakpoint(context, message)
end
end

# Whether asserts should be ignored if not in debug mode.
# Debug mode can be enabled by running ruby with the -d
# switch or by setting $DEBUG to true.
attr_accessor :eek:ptimize_asserts
self.optimize_asserts = false

class DRbService
class FinishedException < Exception; end

include DRbUndumped

def initialize
@breakpoint = @result = nil
@has_breakpoint = @is_done = false
end

def add_breakpoint(context, message)
workspace = IRB::WorkSpace.new(context)
workspace.extend(DRbUndumped)

@breakpoint = [workspace, message]
@has_breakpoint = true

until @is_done; end
@is_done = false
end

def handle_breakpoint(&block)
until @has_breakpoint; end
@has_breakpoint = false

#begin
yield(@breakpoint)
#rescue FinishedException
#end

@is_done = true
end
end

# Will run Breakpoint in DRb mode. This will spawn a server
# that can be attached to via the [ TODO: command ] command
# whenever a breakpoint is executed. This is useful when you
# are debugging CGI applications or other applications where
# you can't access debug sessions via the standard input and
# output of your application.
#
# You can specify an URI where the DRb server will run at.
# This way you can specify the port the server runs on. The
# default URI is druby://localhost:42531.
#
# Please note that breakpoints will be skipped silently in
# case the DRb server can not spawned. (This can happen if
# the port is already used by another instance of your
# application on CGI or another application.)
def activate_drb(uri = 'druby://localhost:42531')
@use_drb = true
@drb_service = DRbService.new
DRb.start_service(uri, @drb_service)
end

def use_drb?
@use_drb == true
end
end

module IRB
def IRB.start(ap_path = nil, main_context = nil, workspace = nil)
$0 = File::basename(ap_path, ".rb") if ap_path

# suppress some warnings about redefined constants
old_verbose, $VERBOSE = $VERBOSE, nil
IRB.setup(ap_path)
$VERBOSE = old_verbose

if @CONF[:SCRIPT] then
irb = Irb.new(main_context, @CONF[:SCRIPT])
else
irb = Irb.new(main_context)
end

if workspace then
irb.context.workspace = workspace
end

@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
@CONF[:MAIN_CONTEXT] = irb.context

trap("SIGINT") do
irb.signal_handle
end

catch:)IRB_EXIT) do
irb.eval_input
end
end

class << self; alias :eek:ld_CurrentContext :CurrentContext; end
def IRB.CurrentContext
if old_CurrentContext.nil? and Breakpoint.use_drb? then
result = Object.new
def result.last_value; end
return result
else
old_CurrentContext
end
end

class Context
alias :eek:ld_evaluate :evaluate
def evaluate(line, line_no)
if line.chomp == "exit" then
exit
else
old_evaluate(line, line_no)
end
end
end

class WorkSpace
alias :eek:ld_evaluate :evaluate

def evaluate(*args)
if Breakpoint.use_drb? then
result = old_evaluate(*args)
result.extend(DRbUndumped) rescue nil
return result
else
old_evaluate(*args)
end
end
end
end

class DRb::DRbObject
undef :inspect
end

def breakpoint(id = nil, &block)
Binding.of_caller do |context|
Breakpoint.breakpoint(id, context, &block)
end
end

def assert(&block)
Binding.of_caller do |context|
Breakpoint.assert(context, &block)
end
end

require 'breakpoint'

if ARGV[0] == "--help" then
puts "This tool lets you connect to a breakpoint service ",
"which was started via Breakpoint.activate_drb.",
"",
"Usage: ruby #{$0} [drb uri]",
"",
"The drb uri defaults to druby://localhost:42531"

exit
end

uri = ARGV[0] || 'druby://localhost:42531'

DRb.start_service

begin
service = DRbObject.new(nil, uri)
loop do
begin
service.handle_breakpoint do |(workspace, message)|
puts message
IRB.start(nil, nil, workspace)
end
rescue Breakpoint::DRbService::FinishedException
end
end
rescue Exception => error
puts "No connection to breakpoint service at #{uri}:",
" (#{error})",
" Reconnecting in 10 seconds..."
sleep 10
retry
end
 
G

Gavin Kistner

Breakpoint.rb is a small library that lets you set breakpoints by
calling a method. When executed, a breakpoint causes an interactive
ruby session to be spawned with the current context. This makes it
especially useful for debugging because Ruby has powerful built-in
capabilities for exploring object environments. (Kernel#caller,
Object#inspect, Object#respond_to?, Kernel#local_variables,
Object#instance_variables and so on.)

Because I'm too lazy to fully inspect both packages, can you describe
how this differs from dev-utils/debug?
 
G

Gavin Sinclair

Because I'm too lazy to fully inspect both packages, can you describe
how this differs from dev-utils/debug?

I can. The early unreleased dev-utils/debug and the original
breakpoint.rb were independent works solving the same problem.
Florian went further than I did and I slurped it right up. So there's
no difference between them, based on what you've quoted.

Now Florian's gone further again, and implemented remote debugging.
That will eventually make its way into dev-utils/debug as well.

Cheers,
Gavin
 
A

Alexey Verkhovsky

This new version includes support for remote debugging via DRb. Using
this you can now also debug your CGI and Rails applications

Thank you SO much!

One small inconvenience that I have with this library is that it takes
some typing to set a breakpoint.

Say I have a util.rb file that is included more or less everywhere in my
app, and I would like to include there something like this:

def bp
require 'breakpoint'
breakpoint
end

so that setting a breakpoint would be simply 'bp'

This doesn't work, of course, because it opens irb in a wrong stack
frame (within bp method).

Any Ruby black magic to somehow inline it in the right stack frame?

Alex
 
M

Mikael Brockman

Alexey Verkhovsky said:
Thank you SO much!

One small inconvenience that I have with this library is that it takes
some typing to set a breakpoint.

Say I have a util.rb file that is included more or less everywhere in my
app, and I would like to include there something like this:

def bp
require 'breakpoint'
breakpoint
end

so that setting a breakpoint would be simply 'bp'

This doesn't work, of course, because it opens irb in a wrong stack
frame (within bp method).

Any Ruby black magic to somehow inline it in the right stack frame?

Maybe you could use Florian Groß's Binding.of_caller to evaluate
'breakpoint' in the caller's binding.
 
F

Florian Gross

Alexey said:
Thank you SO much!

Glad I could provide something useful. :)

BTW, have you tested the remote debugging facilities yet? Any
suggestions / problems?
One small inconvenience that I have with this library is that it takes
some typing to set a breakpoint.

Say I have a util.rb file that is included more or less everywhere in my
app, and I would like to include there something like this:

def bp
require 'breakpoint'
breakpoint
end

so that setting a breakpoint would be simply 'bp'

This doesn't work, of course, because it opens irb in a wrong stack
frame (within bp method).

alias :bp :breakpoint ought to work. You will have to do the require
manually, however. (But it should not cause any overhead anyway.)

Regards,
Florian Gross
 
A

Alexey Verkhovsky

Alexey Verkhovsky wrote:

I don't want to require 'breakpoint' outside a bp method - other people
may not have it installed, and it will be an installation hassle then.
That's the main problem.

Alex
 
F

Florian Gross

Alexey said:
I don't want to require 'breakpoint' outside a bp method - other people
may not have it installed, and it will be an installation hassle then.
That's the main problem.

You could use Binding.of_caller then, but I'm not sure if you want to
have that dependency...

Regards,
Florian Gross
 
A

Alexey Verkhovsky

You could use Binding.of_caller then, but I'm not sure if you want to
have that dependency...

Same problem - non-standard library. But...

Cheap and cheerful solutions being the essence of Russian engineering
ideal, I ended up copying both your classes to my CVS.
:)

Brgds,
Alex
 
B

Brian Candler

This is very cool.

Just one observation: when running over DRb, you have to be very careful not
to type anything in the session which causes another breakpoint to trigger,
as it seems to get rather confused.

For example, in your Person example, at the second breakpoint typing 'name'
instead of '@name' causes a nested breakpoint call. This works just fine for
a directly-connected session:

$ ruby test.rb
Executing break point "Person#initialize" at test.rb:7 in `initialize'
irb(#<Person:0x8130f5c>):001:0> exit
Executing break point "Person#name" at test.rb:13 in `name'
irb(#<Person:0x8130f5c>):001:0> @name
=> "Random Person"
irb(#<Person:0x8130f5c>):002:0> name
Executing break point "Person#name" at test.rb:13 in `name'
irb(#<Person:0x8130f5c>):001:0> name
Executing break point "Person#name" at test.rb:13 in `name'
irb(#<Person:0x8130f5c>):001:0> exit
=> "Random Person"
irb(#<Person:0x8130f5c>):002:0> exit
=> "Random Person"
irb(#<Person:0x8130f5c>):003:0> exit
Name: Random Person

But not over DRb (it hangs at the nested breakpoint). Interestingly, I even
managed to make Ruby dump core in the program which was under test. Gory
details below.

I wonder if a 'console' model would work better; that is, run a private IRB
session in the object under test, and then just connect its input/output
stream? The debug session could accept a telnet connection, or communicate
over a socket or a pair of named pipes.

Also, if it could display +/-5 lines of source code context, that would be
very pleasant. But perhaps then it's getting too close to an IDE :)

Regards,

Brian.

[brian@vaio lib]$ ruby test.rb &
[1] 71708
[brian@vaio lib]$ ruby breakpoint-client.rb
Executing break point "Person#initialize" at test.rb:7 in `initialize'
irb(#<DRb::DRbUnknown:0x8110728>):001:0> exit
Executing break point "Person#name" at test.rb:13 in `name'
irb(#<DRb::DRbUnknown:0x82e93e8>):001:0> @name
=> "Random Person"
irb(#<Person:0x8130c8c>):002:0> name
<< nothing happens here until I press ctrl-C >>
^CIRB::Abort: abort then interrupt!!
from /usr/local/lib/ruby/1.8/irb.rb:81:in `load'
from /usr/local/lib/ruby/1.8/drb/drb.rb:611:in `recv_reply'
from /usr/local/lib/ruby/1.8/drb/drb.rb:865:in `recv_reply'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1104:in `send_message'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1015:in `method_missing'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1014:in `open'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1014:in `method_missing'
from /usr/local/lib/ruby/1.8/irb/context.rb:198:in `old_evaluate'
from ./breakpoint.rb:239:in `evaluate'
from /usr/local/lib/ruby/1.8/irb.rb:148:in `eval_input'
from /usr/local/lib/ruby/1.8/irb.rb:145:in `signal_status'
from /usr/local/lib/ruby/1.8/irb.rb:145:in `eval_input'
from /usr/local/lib/ruby/1.8/irb.rb:144:in `each_top_level_statement'
from /usr/local/lib/ruby/1.8/irb/ruby-lex.rb:220:in `loop'
from /usr/local/lib/ruby/1.8/irb/ruby-lex.rb:220:in `each_top_level_statement'
from /usr/local/lib/ruby/1.8/irb/ruby-lex.rb:219:in `catch'
... 6 levels...
from breakpoint-client.rb:22:in `call'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1434:in `__send__'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1434:in `perform_without_block'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1395:in `perform'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1468:in `main_loop'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1464:in `loop'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1464:in `main_loop'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1460:in `start'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1460:in `main_loop'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1327:in `run'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1324:in `start'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1324:in `run'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1249:in `initialize'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1505:in `new'
from /usr/local/lib/ruby/1.8/drb/drb.rb:1505:in `start_service'
from breakpoint-client.rb:16irb(#<Person:0x8130c8c>):003:0> @name
=> "Random Person"
irb(#<Person:0x8130c8c>):004:0> Name: Random Person
/breakpoint.rb:148: [BUG] Segmentation fault
ruby 1.8.2 (2004-07-29) [i386-freebsd4]

No connection to breakpoint service at druby://localhost:42531:
(connection closed)
Reconnecting in 10 seconds...
^C
<< no response to ^C so I had to do ^Z >>
^Z[1] Abort trap (core dumped) ruby test.rb

[2]+ Stopped ruby breakpoint-client.rb
[brian@vaio lib]$ kill %2
[2]+ Terminated ruby breakpoint-client.rb
[brian@vaio lib]$ jobs
[brian@vaio lib]$ gdb -c ruby.core ruby
GNU gdb 4.18 (FreeBSD)
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-unknown-freebsd"...
(no debugging symbols found)...
Core was generated by `ruby'.
Program terminated with signal 6, Abort trap.
Reading symbols from /usr/local/lib/libruby18.so.18...
(no debugging symbols found)...done.
Reading symbols from /usr/lib/libcrypt.so.2...(no debugging symbols found)...
done.
Reading symbols from /usr/lib/libm.so.2...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libc.so.4...(no debugging symbols found)...done.
Reading symbols from /usr/local/lib/ruby/1.8/i386-freebsd4/readline.so...
(no debugging symbols found)...done.
Reading symbols from /usr/lib/libreadline.so.4...
(no debugging symbols found)...done.
Reading symbols from /usr/lib/libncurses.so.5...(no debugging symbols found)...
done.
Reading symbols from /usr/local/lib/ruby/1.8/i386-freebsd4/socket.so...
(no debugging symbols found)...done.
Reading symbols from /usr/local/lib/ruby/1.8/i386-freebsd4/fcntl.so...
(no debugging symbols found)...done.
Reading symbols from /usr/libexec/ld-elf.so.1...(no debugging symbols found)...
done.
#0 0x28190084 in kill () from /usr/lib/libc.so.4
(gdb) bt
#0 0x28190084 in kill () from /usr/lib/libc.so.4
#1 0x281d197a in abort () from /usr/lib/libc.so.4
#2 0x280827d1 in rb_bug () from /usr/local/lib/libruby18.so.18
#3 0x280e6e82 in sigsegv () from /usr/local/lib/libruby18.so.18
#4 0xbfbfffac in ?? ()
#5 0x2809127f in eval () from /usr/local/lib/libruby18.so.18
#6 0x2809166e in rb_f_eval () from /usr/local/lib/libruby18.so.18
#7 0x2808fb22 in rb_call0 () from /usr/local/lib/libruby18.so.18
#8 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#9 0x2808abd4 in rb_eval () from /usr/local/lib/libruby18.so.18
#10 0x2809015a in rb_call0 () from /usr/local/lib/libruby18.so.18
#11 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#12 0x2808abd4 in rb_eval () from /usr/local/lib/libruby18.so.18
#13 0x2808b54e in rb_eval () from /usr/local/lib/libruby18.so.18
#14 0x2809015a in rb_call0 () from /usr/local/lib/libruby18.so.18
#15 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#16 0x28090778 in rb_f_send () from /usr/local/lib/libruby18.so.18
#17 0x2808fb22 in rb_call0 () from /usr/local/lib/libruby18.so.18
#18 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#19 0x2808a9af in rb_eval () from /usr/local/lib/libruby18.so.18
#20 0x2809015a in rb_call0 () from /usr/local/lib/libruby18.so.18
#21 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#22 0x2808ac4c in rb_eval () from /usr/local/lib/libruby18.so.18
#23 0x2808b60e in rb_eval () from /usr/local/lib/libruby18.so.18
#24 0x28089fd6 in rb_eval () from /usr/local/lib/libruby18.so.18
#25 0x2809015a in rb_call0 () from /usr/local/lib/libruby18.so.18
#26 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#27 0x2808a9af in rb_eval () from /usr/local/lib/libruby18.so.18
#28 0x28089de1 in rb_eval () from /usr/local/lib/libruby18.so.18
---Type <return> to continue, or q <return> to quit---
#29 0x2808b504 in rb_eval () from /usr/local/lib/libruby18.so.18
#30 0x2808a11c in rb_eval () from /usr/local/lib/libruby18.so.18
#31 0x2808dceb in rb_yield_0 () from /usr/local/lib/libruby18.so.18
#32 0x2808e11e in rb_f_loop () from /usr/local/lib/libruby18.so.18
#33 0x2808fb51 in rb_call0 () from /usr/local/lib/libruby18.so.18
#34 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#35 0x2808abd4 in rb_eval () from /usr/local/lib/libruby18.so.18
#36 0x28089a8a in rb_eval () from /usr/local/lib/libruby18.so.18
#37 0x2808dceb in rb_yield_0 () from /usr/local/lib/libruby18.so.18
#38 0x2809a129 in rb_thread_yield () from /usr/local/lib/libruby18.so.18
#39 0x28099e47 in rb_thread_start_0 () from /usr/local/lib/libruby18.so.18
#40 0x2809a252 in rb_thread_start () from /usr/local/lib/libruby18.so.18
#41 0x2808fb22 in rb_call0 () from /usr/local/lib/libruby18.so.18
#42 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#43 0x2808a9af in rb_eval () from /usr/local/lib/libruby18.so.18
#44 0x28089a8a in rb_eval () from /usr/local/lib/libruby18.so.18
#45 0x2809015a in rb_call0 () from /usr/local/lib/libruby18.so.18
#46 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#47 0x2808ac4c in rb_eval () from /usr/local/lib/libruby18.so.18
#48 0x28089666 in rb_eval () from /usr/local/lib/libruby18.so.18
#49 0x2808a11c in rb_eval () from /usr/local/lib/libruby18.so.18
#50 0x2808dceb in rb_yield_0 () from /usr/local/lib/libruby18.so.18
#51 0x2809a129 in rb_thread_yield () from /usr/local/lib/libruby18.so.18
#52 0x28099e47 in rb_thread_start_0 () from /usr/local/lib/libruby18.so.18
#53 0x2809a252 in rb_thread_start () from /usr/local/lib/libruby18.so.18
#54 0x2808fb22 in rb_call0 () from /usr/local/lib/libruby18.so.18
#55 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#56 0x2808a9af in rb_eval () from /usr/local/lib/libruby18.so.18
#57 0x28089a8a in rb_eval () from /usr/local/lib/libruby18.so.18
---Type <return> to continue, or q <return> to quit---
#58 0x2809015a in rb_call0 () from /usr/local/lib/libruby18.so.18
#59 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#60 0x2808ac4c in rb_eval () from /usr/local/lib/libruby18.so.18
#61 0x2808b60e in rb_eval () from /usr/local/lib/libruby18.so.18
#62 0x2809015a in rb_call0 () from /usr/local/lib/libruby18.so.18
#63 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#64 0x280908d5 in rb_funcall2 () from /usr/local/lib/libruby18.so.18
#65 0x2809309c in rb_obj_call_init () from /usr/local/lib/libruby18.so.18
#66 0x280b850b in rb_class_new_instance () from /usr/local/lib/libruby18.so.18
#67 0x2808fb22 in rb_call0 () from /usr/local/lib/libruby18.so.18
#68 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#69 0x2808a9af in rb_eval () from /usr/local/lib/libruby18.so.18
#70 0x2808b60e in rb_eval () from /usr/local/lib/libruby18.so.18
#71 0x2809015a in rb_call0 () from /usr/local/lib/libruby18.so.18
#72 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#73 0x2808a9af in rb_eval () from /usr/local/lib/libruby18.so.18
#74 0x2809015a in rb_call0 () from /usr/local/lib/libruby18.so.18
#75 0x280905e4 in rb_call () from /usr/local/lib/libruby18.so.18
#76 0x2808a9af in rb_eval () from /usr/local/lib/libruby18.so.18
#77 0x28086168 in eval_node () from /usr/local/lib/libruby18.so.18
#78 0x280866fe in ruby_exec () from /usr/local/lib/libruby18.so.18
#79 0x28086771 in ruby_run () from /usr/local/lib/libruby18.so.18
#80 0x80485df in main ()
#81 0x8048516 in _start ()
(gdb)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,961
Messages
2,570,130
Members
46,689
Latest member
liammiller

Latest Threads

Top