tags:

views:

186

answers:

2

I am writing a web based debugger for Ruby, but in order to do this I need to be able to call the Ruby debugger from within a Ruby program on the server side. Has this ever been done? Is this even possible?

The end product being built will allow Ruby code to be edited, executed and stepped through using just a web browser. The ruby code that is to be debugged will be "eval"ed on the server side.

I have since been pointed in the right direction by one of the stackoverflow users who has suggested using popen or expect. I have tried both of these now but have encountered the following problems:

popen: When waiting for the console you have to use a timeout block to signal the end of the debug console's output (The command line terminal can detect this, so why can't ruby).

expect: In the program below the debugger inputs get out of sync with the debugger. Why is that?

require 'pty'
require 'expect'

$expect_verbose = true
PTY.spawn("rdebug deb.rb") do |from_debugger, to_debugger, pid|

    a=nil

    while ( a != "end" ) do

        from_debugger.expect(/\(rdb:1\)/ ) do |input|

            a = gets
            to_debugger.puts( a + "\n" )

        end
        from_debugger.flush
    end

end
+1  A: 

I think you could make use of ruby-debug. I would imagine this as opening the same script on the server-side, and sending keystrokes to it. I think this is how I'd do it.

Think about it this way: the client pastes his code in your form. Optionally, he may click on some button that places a breakpoint on some line. Then he submits the whole thing. On server side, you process that form, and create a .rb file with the contents of the form. At the line where he put the breakpoint, you insert a debugger call. Then you run :

ruby client_script.rb

and this will stop the process once it reaches the debugger line. I would suggest you do all of this with Expect for Ruby or whatever. So, when the client presses step over on the page or inspect whatever variable, you send keystrokes to the process you spawned. For example, if he wants to inspect the value of the variable x, you'd send this to the process:

p x

and you'd have to capture that output and send it back to the client's browser. Expect is kind of like popen , but a bit better.

Geo
Yes, I've tried ruby-debug, but it only allows inspection manually from the console as far as I can tell. I need something where when a breakpoint is hit then a ruby program can manually step over, or inspect variables
Zubair
Sorry, I didn't understand your answer properly... reading it again I understand that you suggest sending keystrokes to "ruby-debug". I will look into this as I didn't even realise that it was possible
Zubair
Actually I wanted to debug "eval"ed code, so using ruby-debug would be an issue as it can only debug a .rb file. Am I correct in thinking this?
Zubair
I've updated the answer.
Geo
Ok, thanks. I'm looking at Expect and Popen now to see if they could do this. Also, I'm wondering if there is some way of evaluating the evaled code within the ruby process by using continuations or blocks and yields (just a thought). Anyway, I'll post my results here.
Zubair
Just came across another problem. Ruby 1.9 doesn't support ruby-debug. Try:gem install ruby-debug : from Ubuntu 8.1 Ruby 1.9 and it says that the gem does not appear in a repository....
Zubair
Try to download the gem manually, and then do: `gem install /path/to/ruby-debug.gem`. It may work.
Geo
Ah, got it, apparently for 1.9 need to do :gem install ruby-debug19: the 19 at the end makes a difference. I'll continue my investigation now!
Zubair
oops, now I'm finding that the same problem exists with expect and popen, both of them don't exist as 1.9 gems... maybe I should just copy and paste the "expect" code you showed me in the link. By the way, I want to add points for your answer but stackoverflow says I cannot add points yet as I don't have even 15 points myself yet, but as soon as I have some points I will award some to you
Zubair
No problem, take your time. Maybe you can manage using only the `popen` module. You can find usage examples here: http://whynotwiki.com/Ruby_/_Process_management
Geo
Hi, I've modified the quesiton a bit. I still can't get popen or expect to work as I needed though
Zubair
I finally figured this out. Thanks
Zubair
How did you finally do it?
Geo
I've posted the result as an answer below, but you are right, uses pty and expect.
Zubair
A: 

I finally figured out how to do this using expect:

require 'pty'
require 'expect'

PTY.spawn("rdebug deb.rb") do |output,input,pid|
    while true do
        begin    
            buffer = ""
            puts "-------"
            puts output.readpartial(1024,buffer) until buffer =~ /\(rdb:1\)/
            a = gets
            input.puts a
        rescue
            break
        end
    end
end
Zubair