| 1 |
require 'breakpoint' |
|---|
| 2 |
require 'optparse' |
|---|
| 3 |
require 'timeout' |
|---|
| 4 |
|
|---|
| 5 |
Options = { |
|---|
| 6 |
:ClientURI => nil, |
|---|
| 7 |
:ServerURI => "druby://localhost:42531", |
|---|
| 8 |
:RetryDelay => 2, |
|---|
| 9 |
:Permanent => true, |
|---|
| 10 |
:Verbose => false |
|---|
| 11 |
} |
|---|
| 12 |
|
|---|
| 13 |
ARGV.options do |opts| |
|---|
| 14 |
script_name = File.basename($0) |
|---|
| 15 |
opts.banner = [ |
|---|
| 16 |
"Usage: ruby #{script_name} [Options] [server uri]", |
|---|
| 17 |
"", |
|---|
| 18 |
"This tool lets you connect to a breakpoint service ", |
|---|
| 19 |
"which was started via Breakpoint.activate_drb.", |
|---|
| 20 |
"", |
|---|
| 21 |
"The server uri defaults to druby://localhost:42531" |
|---|
| 22 |
].join("\n") |
|---|
| 23 |
|
|---|
| 24 |
opts.separator "" |
|---|
| 25 |
|
|---|
| 26 |
opts.on("-c", "--client-uri=uri", |
|---|
| 27 |
"Run the client on the specified uri.", |
|---|
| 28 |
"This can be used to specify the port", |
|---|
| 29 |
"that the client uses to allow for back", |
|---|
| 30 |
"connections from the server.", |
|---|
| 31 |
"Default: Find a good URI automatically.", |
|---|
| 32 |
"Example: -c druby://localhost:12345" |
|---|
| 33 |
) { |v| Options[:ClientURI] = v } |
|---|
| 34 |
|
|---|
| 35 |
opts.on("-s", "--server-uri=uri", |
|---|
| 36 |
"Connect to the server specified at the", |
|---|
| 37 |
"specified uri.", |
|---|
| 38 |
"Default: druby://localhost:42531" |
|---|
| 39 |
) { |v| Options[:ServerURI] = v } |
|---|
| 40 |
|
|---|
| 41 |
opts.on("-R", "--retry-delay=delay", Integer, |
|---|
| 42 |
"Automatically try to reconnect to the", |
|---|
| 43 |
"server after delay seconds when the", |
|---|
| 44 |
"connection failed or timed out.", |
|---|
| 45 |
"A value of 0 disables automatical", |
|---|
| 46 |
"reconnecting completely.", |
|---|
| 47 |
"Default: 10" |
|---|
| 48 |
) { |v| Options[:RetryDelay] = v } |
|---|
| 49 |
|
|---|
| 50 |
opts.on("-P", "--[no-]permanent", |
|---|
| 51 |
"Run the breakpoint client in permanent mode.", |
|---|
| 52 |
"This means that the client will keep continue", |
|---|
| 53 |
"running even after the server has closed the", |
|---|
| 54 |
"connection. Useful for example in Rails." |
|---|
| 55 |
) { |v| Options[:Permanent] = v } |
|---|
| 56 |
|
|---|
| 57 |
opts.on("-V", "--[no-]verbose", |
|---|
| 58 |
"Run the breakpoint client in verbose mode.", |
|---|
| 59 |
"Will produce more messages, for example between", |
|---|
| 60 |
"individual breakpoints. This might help in seeing", |
|---|
| 61 |
"that the breakpoint client is still alive, but adds", |
|---|
| 62 |
"quite a bit of clutter." |
|---|
| 63 |
) { |v| Options[:Verbose] = v } |
|---|
| 64 |
|
|---|
| 65 |
opts.separator "" |
|---|
| 66 |
|
|---|
| 67 |
opts.on("-h", "--help", |
|---|
| 68 |
"Show this help message." |
|---|
| 69 |
) { puts opts; exit } |
|---|
| 70 |
opts.on("-v", "--version", |
|---|
| 71 |
"Display the version information." |
|---|
| 72 |
) do |
|---|
| 73 |
id = %q$Id: breakpoint_client.rb 91 2005-02-04 22:34:08Z flgr $ |
|---|
| 74 |
puts id.sub("Id: ", "") |
|---|
| 75 |
puts "(Breakpoint::Version = #{Breakpoint::Version})" |
|---|
| 76 |
exit |
|---|
| 77 |
end |
|---|
| 78 |
|
|---|
| 79 |
opts.parse! |
|---|
| 80 |
end |
|---|
| 81 |
|
|---|
| 82 |
Options[:ServerURI] = ARGV[0] if ARGV[0] |
|---|
| 83 |
|
|---|
| 84 |
module Handlers |
|---|
| 85 |
extend self |
|---|
| 86 |
|
|---|
| 87 |
def breakpoint_handler(workspace, message) |
|---|
| 88 |
puts message |
|---|
| 89 |
IRB.start(nil, nil, workspace) |
|---|
| 90 |
|
|---|
| 91 |
puts "" |
|---|
| 92 |
if Options[:Verbose] then |
|---|
| 93 |
puts "Resumed execution. Waiting for next breakpoint...", "" |
|---|
| 94 |
end |
|---|
| 95 |
end |
|---|
| 96 |
|
|---|
| 97 |
def eval_handler(code) |
|---|
| 98 |
result = eval(code, TOPLEVEL_BINDING) |
|---|
| 99 |
if result then |
|---|
| 100 |
DRbObject.new(result) |
|---|
| 101 |
else |
|---|
| 102 |
result |
|---|
| 103 |
end |
|---|
| 104 |
end |
|---|
| 105 |
|
|---|
| 106 |
def collision_handler() |
|---|
| 107 |
msg = [ |
|---|
| 108 |
" *** Breakpoint service collision ***", |
|---|
| 109 |
" Another Breakpoint service tried to use the", |
|---|
| 110 |
" port already occupied by this one. It will", |
|---|
| 111 |
" keep waiting until this Breakpoint service", |
|---|
| 112 |
" is shut down.", |
|---|
| 113 |
" ", |
|---|
| 114 |
" If you are using the Breakpoint library for", |
|---|
| 115 |
" debugging a Rails or other CGI application", |
|---|
| 116 |
" this likely means that this Breakpoint", |
|---|
| 117 |
" session belongs to an earlier, outdated", |
|---|
| 118 |
" request and should be shut down via 'exit'." |
|---|
| 119 |
].join("\n") |
|---|
| 120 |
|
|---|
| 121 |
if RUBY_PLATFORM["win"] then |
|---|
| 122 |
|
|---|
| 123 |
|
|---|
| 124 |
|
|---|
| 125 |
|
|---|
| 126 |
|
|---|
| 127 |
|
|---|
| 128 |
begin |
|---|
| 129 |
require 'tk' |
|---|
| 130 |
root = TkRoot.new { withdraw } |
|---|
| 131 |
Tk.messageBox('message' => msg, 'type' => 'ok') |
|---|
| 132 |
root.destroy |
|---|
| 133 |
rescue Exception |
|---|
| 134 |
puts "", msg, "" |
|---|
| 135 |
end |
|---|
| 136 |
else |
|---|
| 137 |
puts "", msg, "" |
|---|
| 138 |
end |
|---|
| 139 |
end |
|---|
| 140 |
end |
|---|
| 141 |
|
|---|
| 142 |
|
|---|
| 143 |
reconnecting = false |
|---|
| 144 |
|
|---|
| 145 |
loop do |
|---|
| 146 |
DRb.start_service(Options[:ClientURI]) |
|---|
| 147 |
|
|---|
| 148 |
begin |
|---|
| 149 |
service = DRbObject.new(nil, Options[:ServerURI]) |
|---|
| 150 |
|
|---|
| 151 |
begin |
|---|
| 152 |
ehandler = Handlers.method(:eval_handler) |
|---|
| 153 |
chandler = Handlers.method(:collision_handler) |
|---|
| 154 |
handler = Handlers.method(:breakpoint_handler) |
|---|
| 155 |
service.eval_handler = ehandler |
|---|
| 156 |
service.collision_handler = chandler |
|---|
| 157 |
service.handler = handler |
|---|
| 158 |
|
|---|
| 159 |
reconnecting = false |
|---|
| 160 |
if Options[:Verbose] then |
|---|
| 161 |
puts "Connection established. Waiting for breakpoint...", "" |
|---|
| 162 |
end |
|---|
| 163 |
|
|---|
| 164 |
loop do |
|---|
| 165 |
begin |
|---|
| 166 |
service.ping |
|---|
| 167 |
rescue DRb::DRbConnError => error |
|---|
| 168 |
puts "Server exited. Closing connection...", "" |
|---|
| 169 |
exit! unless Options[:Permanent] |
|---|
| 170 |
break |
|---|
| 171 |
end |
|---|
| 172 |
|
|---|
| 173 |
sleep(0.5) |
|---|
| 174 |
end |
|---|
| 175 |
ensure |
|---|
| 176 |
service.eval_handler = nil |
|---|
| 177 |
service.collision_handler = nil |
|---|
| 178 |
service.handler = nil |
|---|
| 179 |
end |
|---|
| 180 |
rescue Exception => error |
|---|
| 181 |
if Options[:RetryDelay] > 0 then |
|---|
| 182 |
if not reconnecting then |
|---|
| 183 |
reconnecting = true |
|---|
| 184 |
puts "No connection to breakpoint service at #{Options[:ServerURI]} " + |
|---|
| 185 |
"(#{error.class})" |
|---|
| 186 |
puts error.backtrace if $DEBUG |
|---|
| 187 |
puts "Tries to connect will be made every #{Options[:RetryDelay]} seconds..." |
|---|
| 188 |
end |
|---|
| 189 |
|
|---|
| 190 |
sleep Options[:RetryDelay] |
|---|
| 191 |
retry |
|---|
| 192 |
else |
|---|
| 193 |
raise |
|---|
| 194 |
end |
|---|
| 195 |
end |
|---|
| 196 |
end |
|---|