Can a program be made to drop into irb?

I’d like to be able to write a program that, halfway through
execution, stops what it’s doing and opens an irb session with the
current state. This would be an excellent tool for debugging.

Does anyone know if it’s possible? My instinct says it’s probably
not. If that’s the case, I’d like to if some modification to Ruby
could make it possible, to feed into a potential RCR.

Cheers,
Gavin

Hi –

Gavin Sinclair gsinclair@soyabean.com.au writes:

I’d like to be able to write a program that, halfway through
execution, stops what it’s doing and opens an irb session with the
current state. This would be an excellent tool for debugging.

Does anyone know if it’s possible? My instinct says it’s probably
not. If that’s the case, I’d like to if some modification to Ruby
could make it possible, to feed into a potential RCR.

$ ruby -e ‘require “irb”; print "irb? "; IRB.start if /y/.match(gets)’
irb? yes
irb(main):001:0>

New scope, of course, but still running same program. I don’t know
that there’s any way to get local variables involved, except maybe
grabbing the binding directly.

David

···


David A. Black
dblack@wobblini.net

~ > cat a.rb
require ‘irb’
a, b = 4, 2
begin
c = 42
syntax_error
rescue Exception => e
IRB.setup nil
IRB::Irb.new(IRB::WorkSpace.new(binding),nil).eval_input
end

~ > ruby a.rb
irb(main):001:0> p a,b,c
4
2
42
=> nil

i confess i have no idea how this works, but it seems to… you need to type
ctrl-D to get out (end STDIN), i’m not sure how to get back into the program…
perhaps someone else could figure it out…

a shorthand for this would be immensely useful - something like

ret = IRB.debug

-a

···

On Tue, 4 May 2004, Gavin Sinclair wrote:

I’d like to be able to write a program that, halfway through
execution, stops what it’s doing and opens an irb session with the
current state. This would be an excellent tool for debugging.

Does anyone know if it’s possible? My instinct says it’s probably
not. If that’s the case, I’d like to if some modification to Ruby
could make it possible, to feed into a potential RCR.

Cheers,
Gavin

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: Solar-Terrestrial Physics Data | NCEI
TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done
===============================================================================

“David Alan Black” dblack@wobblini.net schrieb im Newsbeitrag
news:m3smeg8h4h.fsf@wobblini.net

Hi –

Gavin Sinclair gsinclair@soyabean.com.au writes:

I’d like to be able to write a program that, halfway through
execution, stops what it’s doing and opens an irb session with the
current state. This would be an excellent tool for debugging.

Does anyone know if it’s possible? My instinct says it’s probably
not. If that’s the case, I’d like to if some modification to Ruby
could make it possible, to feed into a potential RCR.

$ ruby -e ‘require “irb”; print "irb? "; IRB.start if /y/.match(gets)’
irb? yes
irb(main):001:0>

New scope, of course, but still running same program. I don’t know
that there’s any way to get local variables involved, except maybe
grabbing the binding directly.

The program could provide a callback in some global var that presents all
interesting infos. Of course, locals were still not (directly)
accessible, but one could hack something together using set_trace_func.

Otherwise it might be better to use the debugger anyway…

Regards

robert

~ >> cat a.rb

require ‘irb’
a, b = 4, 2
begin
c = 42
syntax_error
rescue Exception =>> e
IRB.setup nil
IRB::Irb.new(IRB::WorkSpace.new(binding),nil).eval_input
end

~ >> ruby a.rb
irb(main):001:0>> p a,b,c

4
2
42
=>> nil

i confess i have no idea how this works, but it seems to… you need to type
ctrl-D to get out (end STDIN), i’m not sure how to get back into the program…
perhaps someone else could figure it out…

a shorthand for this would be immensely useful - something like

ret = IRB.debug

Well, that’s a good start. Getting back to the program would be
handy.

Then calling IRB.debug is like using a debugger, except the
breakpoints are in the code, which I think is a good thing to be able
to do.

Gavin

···

On Wednesday, May 5, 2004, 12:03:56 AM, Ara.T.Howard wrote:

In article m3smeg8h4h.fsf@wobblini.net,

···

David Alan Black dblack@wobblini.net wrote:

Hi –

Gavin Sinclair gsinclair@soyabean.com.au writes:

I’d like to be able to write a program that, halfway through
execution, stops what it’s doing and opens an irb session with the
current state. This would be an excellent tool for debugging.

Does anyone know if it’s possible? My instinct says it’s probably
not. If that’s the case, I’d like to if some modification to Ruby
could make it possible, to feed into a potential RCR.

$ ruby -e ‘require “irb”; print "irb? "; IRB.start if /y/.match(gets)’
irb? yes
irb(main):001:0>

New scope, of course, but still running same program. I don’t know
that there’s any way to get local variables involved, except maybe
grabbing the binding directly.

It would be cool if you could pass in the current binding to IRB.start.
Is that possible?

Phil

This is what I use to break from a program into an irb shell. I set my
app’s interrupt handler to call it, and then reset the interrupt handler
when it is done (where noted). You can go back and forth between app and
shell with ^C and ^D. I usually add some methods to the object that gets
passed to start_session: #help, #commands, methods to pipe data to
gnuplot, etc.

Ara’s idea to pass a binding to Workspace.new is great. Changes to
locals are even persistent after you leave the shell. I’m puzzled about
why that works–maybe irb detects that the object is a binding?

···

#!/usr/bin/env ruby

require 'irb’
require ‘irb/completion’

module IRB
def IRB.parse_opts
# Don’t touch ARGV, which belongs to the app which called this module.
end

def IRB.start_session(object)
unless $irb
IRB.setup nil
## maybe set some opts here, as in parse_opts in irb/init.rb?
end

 workspace = WorkSpace.new(object)

 if @CONF[:SCRIPT] ## normally, set by parse_opts
   $irb = Irb.new(workspace, @CONF[:SCRIPT])
 else
   $irb = Irb.new(workspace)
 end

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

 trap 'INT' do
   $irb.signal_handle
 end

 custom_configuration if defined?(IRB.custom_configuration)

 catch :IRB_EXIT do
   $irb.eval_input
 end

 ## might want to reset your app's interrupt handler here

end
end

class Object
include IRB::ExtendCommandBundle # so that Marshal.dump works
end

if FILE == $0
x = Object.new
puts "\nStarted irb shell for x"
IRB.start_session(x)
puts "\nStarted irb shell for current binding"
IRB.start_session(binding)
puts "\nExited irb shell"
p x
end

Joel VanderWerf wrote:

Ara’s idea to pass a binding to Workspace.new is great. Changes to
locals are even persistent after you leave the shell. I’m puzzled about
why that works–maybe irb detects that the object is a binding?

Yes, that’s what irb does. In irb/workspace.irb:

module IRB
class WorkSpace
# create new workspace. set self to main if specified, otherwise
# inherit main from TOPLEVEL_BINDING.
def initialize(*main)
if main[0].kind_of?(Binding)
@binding = main.shift

So you can get two useful effects with WorkSpace.new:

WorkSpace.new(obj)

 Makes obj the self of a new workspace.

WorkSpace.new(b, obj)

 Makes obj the self of a new workspace, and uses b as the binding.

Thanks Joel. That will give me something to chew over.

Cheers,
Gavin

···

On Wednesday, May 5, 2004, 3:14:14 AM, Joel wrote:

This is what I use to break from a program into an irb shell. […]