提交 8eec6741 编写于 作者: D David Heinemeier Hansson

Breakpointing that works much better with CGI and FCGI

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@136 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 c9cc73d0
......@@ -2,11 +2,4 @@
ActionController::Base.reload_dependencies = true
ActiveRecord::Base.reload_associations = true
require 'breakpoint'
require 'irb/completion'
# Change the port (default: 42531) here in case you are
# on shared hosting. Note that you should set up a SSH
# tunnel when you want to connect from a different
# computer over the internet. See the documentation of
# Breakpoint.activate_drb for how to do that.
Breakpoint.activate_drb('druby://l​ocalhost:42531', nil, !defined?(FastCGI)) if $0.include?("dispatch")
\ No newline at end of file
BREAKPOINT_SERVER_PORT = 42531
\ No newline at end of file
......@@ -5,7 +5,8 @@
options = {
:ClientURI => nil,
:ServerURI => "druby://localhost:42531",
:RetryDelay => 10
:RetryDelay => 1,
:Verbose => false
}
ARGV.options do |opts|
......@@ -36,6 +37,11 @@
"Default: druby://localhost:42531"
) { |options[:ServerURI]| }
opts.on("-v", "--verbose",
"Report all connections and disconnections",
"Default: false"
) { |options[:Verbose]| }
opts.on("-R", "--retry-delay=delay", Integer,
"Automatically try to reconnect to the",
"server after delay seconds when the",
......@@ -56,97 +62,103 @@
options[:ServerURI] = ARGV[0] if ARGV[0]
DRb.start_service(options[:ClientURI])
puts "Waiting for initial breakpoint..."
begin
service = DRbObject.new(nil, options[:ServerURI])
loop do
DRb.start_service(options[:ClientURI])
begin
timeout(10) { service.ping }
rescue Timeout::Error, DRb::DRbConnError
puts "",
" *** Breakpoint service didn't respond to ping request ***",
" This likely happened because of a misconfigured ACL (see the",
" documentation of Breakpoint.activate_drb, note that by default",
" you can only connect to a remote Breakpoint service via a SSH",
" tunnel), but might also be caused by an extremely slow connection.",
""
raise
end
begin
service.register_eval_handler do |code|
result = eval(code, TOPLEVEL_BINDING)
result.extend(DRb::DRbUndumped) rescue nil
result
service = DRbObject.new(nil, options[:ServerURI])
begin
timeout(10) { service.ping }
rescue Timeout::Error, DRb::DRbConnError
if options[:Verbose]
puts "",
" *** Breakpoint service didn't respond to ping request ***",
" This likely happened because of a misconfigured ACL (see the",
" documentation of Breakpoint.activate_drb, note that by default",
" you can only connect to a remote Breakpoint service via a SSH",
" tunnel), but might also be caused by an extremely slow connection.",
""
end
raise
end
service.register_collision_handler do
msg = [
" *** Breakpoint service collision ***",
" Another Breakpoint service tried to use the",
" port already occupied by this one. It will",
" keep waiting until this Breakpoint service",
" is shut down.",
" ",
" If you are using the Breakpoint library for",
" debugging a Rails or other CGI application",
" this likely means that this Breakpoint",
" session belongs to an earlier, outdated",
" request and should be shut down via 'exit'."
].join("\n")
if RUBY_PLATFORM["win"] then
# This sucks. Sorry, I'm not doing this because
# I like funky message boxes -- I need to do this
# because on Windows I have no way of displaying
# my notification via puts() when gets() is still
# being performed on STDIN. I have not found a
# better solution.
begin
require 'tk'
root = TkRoot.new { withdraw }
Tk.messageBox('message' => msg, 'type' => 'ok')
root.destroy
rescue Exception
begin
service.register_eval_handler do |code|
result = eval(code, TOPLEVEL_BINDING)
result.extend(DRb::DRbUndumped) rescue nil
result
end
service.register_collision_handler do
msg = [
" *** Breakpoint service collision ***",
" Another Breakpoint service tried to use the",
" port already occupied by this one. It will",
" keep waiting until this Breakpoint service",
" is shut down.",
" ",
" If you are using the Breakpoint library for",
" debugging a Rails or other CGI application",
" this likely means that this Breakpoint",
" session belongs to an earlier, outdated",
" request and should be shut down via 'exit'."
].join("\n")
if RUBY_PLATFORM["win"] then
# This sucks. Sorry, I'm not doing this because
# I like funky message boxes -- I need to do this
# because on Windows I have no way of displaying
# my notification via puts() when gets() is still
# being performed on STDIN. I have not found a
# better solution.
begin
require 'tk'
root = TkRoot.new { withdraw }
Tk.messageBox('message' => msg, 'type' => 'ok')
root.destroy
rescue Exception
puts "", msg, ""
end
else
puts "", msg, ""
end
else
puts "", msg, ""
end
end
service.register_handler do |workspace, message|
puts message
IRB.start(nil, nil, workspace)
puts "", "Resumed execution. Waiting for next breakpoint...", ""
end
service.register_handler do |workspace, message|
puts message
IRB.start(nil, nil, workspace)
puts "", "Resumed execution. Waiting for next breakpoint...", ""
end
puts "Connection established. Waiting for breakpoint...", ""
puts "Connection established. Waiting for breakpoint...", "" if options[:Verbose]
loop do
begin
service.ping
rescue DRb::DRbConnError => error
puts "Server exited. Exiting..."
exit!
end
loop do
begin
service.ping
rescue DRb::DRbConnError => error
puts "Server exited. Closing connection..." if options[:Verbose]
break
end
sleep(0.5)
sleep(0.5)
end
ensure
service.unregister_handler
end
ensure
service.unregister_handler
end
rescue Exception => error
if options[:RetryDelay] > 0 then
puts "No connection to breakpoint service at #{options[:ServerURI]}:",
" (#{error.inspect})"
puts error.backtrace if $DEBUG
puts " Reconnecting in #{options[:RetryDelay]} seconds..."
rescue Exception => error
if options[:RetryDelay] > 0 then
puts "No connection to breakpoint service at #{options[:ServerURI]}:", " (#{error.inspect})" if options[:Verbose]
error.backtrace if $DEBUG
puts " Reconnecting in #{options[:RetryDelay]} seconds..." if options[:Verbose]
sleep options[:RetryDelay]
retry
else
raise
sleep options[:RetryDelay]
retry
else
raise
end
end
end
\ No newline at end of file
......@@ -21,10 +21,14 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
require 'breakpoint'
class Dispatcher
DEFAULT_SESSION_OPTIONS = { :database_manager => CGI::Session::PStore, :prefix => "ruby_sess.", :session_path => "/" }
def self.dispatch(cgi = CGI.new, session_options = DEFAULT_SESSION_OPTIONS)
Breakpoint.activate_drb("druby://localhost:#{BREAKPOINT_SERVER_PORT}", nil, !defined?(FastCGI)) if defined?(BREAKPOINT_SERVER_PORT)
begin
request = ActionController::CgiRequest.new(cgi, session_options)
response = ActionController::CgiResponse.new(cgi)
......@@ -44,6 +48,8 @@ def self.dispatch(cgi = CGI.new, session_options = DEFAULT_SESSION_OPTIONS)
ActiveRecord::Base.reset_associations_loaded
ActiveRecord::Base.reset_column_information_and_inheritable_attributes_for_all_subclasses
end
DRb.stop_service if defined?(BREAKPOINT_SERVER_PORT)
end
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册