From 70ac560e42644938392381ecd52efd7fb0260323 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 28 Apr 2007 15:57:29 +0000 Subject: [PATCH] Removed breakpointer and Binding.of_caller in favor of relying on ruby-debug by Kent Sibilev since the breakpointer has been broken since Ruby 1.8.4 and will not be coming back [DHH] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6611 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/lib/action_controller/rescue.rb | 24 - .../rescues/_request_and_response.erb | 20 - actionpack/test/abstract_unit.rb | 1 - .../connection_adapters/openbase_adapter.rb | 1 - activerecord/test/abstract_unit.rb | 2 - activeresource/test/abstract_unit.rb | 1 - activesupport/CHANGELOG | 2 + .../lib/active_support/binding_of_caller.rb | 84 --- .../lib/active_support/breakpoint.rb | 528 ----------------- .../lib/active_support/core_ext/kernel.rb | 1 + .../core_ext/kernel/debugger.rb | 13 + railties/CHANGELOG | 12 + railties/README | 18 +- railties/Rakefile | 2 +- railties/bin/breakpointer | 3 - railties/environments/development.rb | 3 - railties/lib/binding_of_caller.rb | 85 --- railties/lib/breakpoint.rb | 553 ------------------ railties/lib/breakpoint_client.rb | 196 ------- railties/lib/commands/breakpointer.rb | 1 - railties/lib/commands/servers/base.rb | 12 + railties/lib/commands/servers/mongrel.rb | 6 +- railties/lib/commands/servers/webrick.rb | 20 +- railties/lib/dispatcher.rb | 11 - railties/lib/fcgi_handler.rb | 20 +- railties/lib/initializer.rb | 16 - .../applications/app/app_generator.rb | 2 +- railties/lib/test_help.rb | 1 - railties/test/fcgi_dispatcher_test.rb | 28 - 29 files changed, 69 insertions(+), 1597 deletions(-) delete mode 100644 activesupport/lib/active_support/binding_of_caller.rb delete mode 100755 activesupport/lib/active_support/breakpoint.rb create mode 100644 activesupport/lib/active_support/core_ext/kernel/debugger.rb delete mode 100644 railties/bin/breakpointer delete mode 100644 railties/lib/binding_of_caller.rb delete mode 100644 railties/lib/breakpoint.rb delete mode 100644 railties/lib/breakpoint_client.rb delete mode 100644 railties/lib/commands/breakpointer.rb diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb index cd3a1b5650..225acd28f3 100644 --- a/actionpack/lib/action_controller/rescue.rb +++ b/actionpack/lib/action_controller/rescue.rb @@ -124,30 +124,6 @@ def rescue_action_locally(exception) def perform_action_with_rescue #:nodoc: perform_action_without_rescue rescue Exception => exception # errors from action performed - if defined?(Breakpoint) && params["BP-RETRY"] - msg = exception.backtrace.first - if md = /^(.+?):(\d+)(?::in `(.+)')?$/.match(msg) then - origin_file, origin_line = md[1], md[2].to_i - - set_trace_func(lambda do |type, file, line, method, context, klass| - if file == origin_file and line == origin_line then - set_trace_func(nil) - params["BP-RETRY"] = false - - callstack = caller - callstack.slice!(0) if callstack.first["rescue.rb"] - file, line, method = *callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures - - message = "Exception at #{file}:#{line}#{" in `#{method}'" if method}." # `´ ( for ruby-mode) - - Breakpoint.handle_breakpoint(context, message, file, line) - end - end) - - retry - end - end - rescue_action(exception) end diff --git a/actionpack/lib/action_controller/templates/rescues/_request_and_response.erb b/actionpack/lib/action_controller/templates/rescues/_request_and_response.erb index fe60bfdd40..64b34650b1 100644 --- a/actionpack/lib/action_controller/templates/rescues/_request_and_response.erb +++ b/actionpack/lib/action_controller/templates/rescues/_request_and_response.erb @@ -5,26 +5,6 @@
><%=h @exception.describe_blame %>
<% end %> -<% if false %> -

- <% begin %> - <%= form_tag(request.request_uri, "method" => request.method) %> - - - <% for key, values in params %> - <% next if key == "BP-RETRY" %> - <% for value in Array(values) %> - - <% end %> - <% end %> - - - - <% rescue Exception => e %> - <%=h "Couldn't render breakpoint link due to #{e.class} #{e.message}" %> - <% end %> -<% end %> - <% clean_params = request.parameters.clone clean_params.delete("action") diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 2733ed95da..e4b8b5b04a 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -5,7 +5,6 @@ require 'yaml' require 'test/unit' require 'action_controller' -require 'breakpoint' require 'action_controller/test_process' # Show backtraces for deprecated behavior for quicker cleanup. diff --git a/activerecord/lib/active_record/connection_adapters/openbase_adapter.rb b/activerecord/lib/active_record/connection_adapters/openbase_adapter.rb index 71143b2202..57d16d47b4 100644 --- a/activerecord/lib/active_record/connection_adapters/openbase_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/openbase_adapter.rb @@ -198,7 +198,6 @@ def columns(table_name, name = nil) #:nodoc: sql_type_name(row["typename"],row["length"]), row["notnull"] ) - # breakpoint() if row["fieldname"] == "content" end columns end diff --git a/activerecord/test/abstract_unit.rb b/activerecord/test/abstract_unit.rb index 5e94fa11b4..c3d4dbe591 100755 --- a/activerecord/test/abstract_unit.rb +++ b/activerecord/test/abstract_unit.rb @@ -4,8 +4,6 @@ require 'test/unit' require 'active_record' require 'active_record/fixtures' -require 'active_support/binding_of_caller' -require 'active_support/breakpoint' require 'connection' # Show backtraces for deprecated behavior for quicker cleanup. diff --git a/activeresource/test/abstract_unit.rb b/activeresource/test/abstract_unit.rb index ca0d1631e9..db1e0b9535 100644 --- a/activeresource/test/abstract_unit.rb +++ b/activeresource/test/abstract_unit.rb @@ -3,7 +3,6 @@ $:.unshift "#{File.dirname(__FILE__)}/../lib" require 'active_resource' require 'active_resource/http_mock' -require 'active_support/breakpoint' $:.unshift "#{File.dirname(__FILE__)}/../test" require 'setter_trap' diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 018d6e977c..f8ac504127 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Removed breakpointer and Binding.of_caller in favor of relying on ruby-debug by Kent Sibilev since the breakpointer has been broken since Ruby 1.8.4 and will not be coming back [DHH] + * Added parsing of file type in Hash.xml_in so you can easily do file uploads with base64 from an API [DHH] diff --git a/activesupport/lib/active_support/binding_of_caller.rb b/activesupport/lib/active_support/binding_of_caller.rb deleted file mode 100644 index e224c996da..0000000000 --- a/activesupport/lib/active_support/binding_of_caller.rb +++ /dev/null @@ -1,84 +0,0 @@ -begin - require 'simplecc' -rescue LoadError - class Continuation # :nodoc: # for RDoc - end - def Continuation.create(*args, &block) # :nodoc: - cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?} - result ||= args - return *[cc, *result] - end -end - -class Binding; end # for RDoc -# 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" then - nil - elsif type == "c-return" and extra_data[3] == :set_trace_func then - nil - else - 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 diff --git a/activesupport/lib/active_support/breakpoint.rb b/activesupport/lib/active_support/breakpoint.rb deleted file mode 100755 index 8207117ced..0000000000 --- a/activesupport/lib/active_support/breakpoint.rb +++ /dev/null @@ -1,528 +0,0 @@ -# The Breakpoint library provides the convenience of -# being able to inspect and modify state, diagnose -# bugs all via IRB by simply setting breakpoints in -# your applications by the call of a method. -# -# This library was written and is supported by me, -# Florian Gross. I can be reached at flgr@ccan.de -# and enjoy getting feedback about my libraries. -# -# The whole library (including breakpoint_client.rb -# and binding_of_caller.rb) is licensed under the -# same license that Ruby uses. (Which is currently -# either the GNU General Public License or a custom -# one that allows for commercial usage.) If you for -# some good reason need to use this under another -# license please contact me. - -require 'irb' -require File.dirname(__FILE__) + '/binding_of_caller' unless defined? Binding.of_caller -require 'drb' -require 'drb/acl' - -module Breakpoint - id = %q$Id: breakpoint.rb 92 2005-02-04 22:35:53Z flgr $ - Version = id.split(" ")[2].to_i - - 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+. - # - # The source code around the location where the breakpoint - # was executed can be examined via +source_lines+. Its - # argument specifies how much lines of context to display. - # The default amount of context is 5 lines. Note that - # the call to +source_lines+ can raise an exception when - # it isn't able to read in the source code. - # - # 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(#):001:0> local_variables - # => ["name", "age", "_", "__"] - # irb(#):002:0> [name, age] - # => ["Random Person", 23] - # irb(#):003:0> [@name, @age] - # => ["Random Person", 23] - # irb(#):004:0> self - # => # - # irb(#):005:0> @age += 1; self - # => # - # irb(#):006:0> exit - # Executing break point "Person#name" at file.rb:9 in `name' - # irb(#):001:0> throw(:debug_return, "Overriden name") - # Name: Overriden name - # - # Breakpoint sessions will automatically have a few - # convenience methods available. See Breakpoint::CommandBundle - # for a list of them. - # - # Breakpoints can also be used remotely over sockets. - # This is implemented by running part of the IRB session - # in the application and part of it in a special client. - # You have to call Breakpoint.activate_drb to enable - # support for remote breakpoints and then run - # breakpoint_client.rb which is distributed with this - # library. See the documentation of Breakpoint.activate_drb - # for details. - 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, file, line, &block) - end - - Binding.of_caller do |binding_context| - handle_breakpoint(binding_context, message, file, line, &block) - end - end - - module CommandBundle #:nodoc: - # Proxy to a Breakpoint client. Lets you directly execute code - # in the context of the client. - class Client #:nodoc: - def initialize(eval_handler) # :nodoc: - eval_handler.untaint - @eval_handler = eval_handler - end - - instance_methods.each do |method| - next if method[/^__.+__$/] - undef_method method - end - - # Executes the specified code at the client. - def eval(code) - @eval_handler.call(code) - end - - # Will execute the specified statement at the client. - def method_missing(method, *args, &block) - if args.empty? and not block - result = eval "#{method}" - else - # This is a bit ugly. The alternative would be using an - # eval context instead of an eval handler for executing - # the code at the client. The problem with that approach - # is that we would have to handle special expressions - # like "self", "nil" or constants ourself which is hard. - remote = eval %{ - result = lambda { |block, *args| #{method}(*args, &block) } - def result.call_with_block(*args, &block) - call(block, *args) - end - result - } - remote.call_with_block(*args, &block) - end - - return result - end - end - - # Returns the source code surrounding the location where the - # breakpoint was issued. - def source_lines(context = 5, return_line_numbers = false) - lines = File.readlines(@__bp_file).map { |line| line.chomp } - - break_line = @__bp_line - start_line = [break_line - context, 1].max - end_line = break_line + context - - result = lines[(start_line - 1) .. (end_line - 1)] - - if return_line_numbers then - return [start_line, break_line, result] - else - return result - end - end - - # Lets an object that will forward method calls to the breakpoint - # client. This is useful for outputting longer things at the client - # and so on. You can for example do these things: - # - # client.puts "Hello" # outputs "Hello" at client console - # # outputs "Hello" into the file temp.txt at the client - # client.File.open("temp.txt", "w") { |f| f.puts "Hello" } - def client() - if Breakpoint.use_drb? then - sleep(0.5) until Breakpoint.drb_service.eval_handler - Client.new(Breakpoint.drb_service.eval_handler) - else - Client.new(lambda { |code| eval(code, TOPLEVEL_BINDING) }) - end - end - end - - def handle_breakpoint(context, message, file = "", line = "", &block) # :nodoc: - catch(:debug_return) do |value| - eval(%{ - @__bp_file = #{file.inspect} - @__bp_line = #{line} - extend Breakpoint::CommandBundle - extend DRbUndumped if self - }, context) rescue nil - - 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 - - # These exceptions will be raised on failed asserts - # if Breakpoint.asserts_cause_exceptions is set to - # true. - class FailedAssertError < RuntimeError #:nodoc: - end - - # 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 in production - # code by setting Breakpoint.optimize_asserts to - # true. (It will still be enabled when Ruby is run - # via the -d argument.) - # - # Example: - # person_name = "Foobar" - # assert { not person_name.nil? } - # - # Note: If you want to use this method from an - # unit test, you will have to call it by its full - # name, Breakpoint.assert. - 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}." - - if Breakpoint.asserts_cause_exceptions and not $DEBUG then - raise(Breakpoint::FailedAssertError, message) - end - - message += " Executing implicit breakpoint." - - if context then - return handle_breakpoint(context, message, file, line) - end - - Binding.of_caller do |context| - handle_breakpoint(context, message, file, line) - 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 :optimize_asserts - self.optimize_asserts = false - - # Whether an Exception should be raised on failed asserts - # in non-$DEBUG code or not. By default this is disabled. - attr_accessor :asserts_cause_exceptions - self.asserts_cause_exceptions = false - @use_drb = false - - attr_reader :drb_service # :nodoc: - - class DRbService # :nodoc: - include DRbUndumped - - def initialize - @handler = @eval_handler = @collision_handler = nil - - IRB.instance_eval { @CONF[:RC] = true } - IRB.run_config - end - - def collision - sleep(0.5) until @collision_handler - - @collision_handler.untaint - - @collision_handler.call - end - - def ping() end - - def add_breakpoint(context, message) - workspace = IRB::WorkSpace.new(context) - workspace.extend(DRbUndumped) - - sleep(0.5) until @handler - - @handler.untaint - @handler.call(workspace, message) - end - - attr_accessor :handler, :eval_handler, :collision_handler - end - - # Will run Breakpoint in DRb mode. This will spawn a server - # that can be attached to via the breakpoint-client 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.) - # - # Also note that by default this will only allow access - # from localhost. You can however specify a list of - # allowed hosts or nil (to allow access from everywhere). - # But that will still not protect you from somebody - # reading the data as it goes through the net. - # - # A good approach for getting security and remote access - # is setting up an SSH tunnel between the DRb service - # and the client. This is usually done like this: - # - # $ ssh -L20000:127.0.0.1:20000 -R10000:127.0.0.1:10000 example.com - # (This will connect port 20000 at the client side to port - # 20000 at the server side, and port 10000 at the server - # side to port 10000 at the client side.) - # - # After that do this on the server side: (the code being debugged) - # Breakpoint.activate_drb("druby://127.0.0.1:20000", "localhost") - # - # And at the client side: - # ruby breakpoint_client.rb -c druby://127.0.0.1:10000 -s druby://127.0.0.1:20000 - # - # Running through such a SSH proxy will also let you use - # breakpoint.rb in case you are behind a firewall. - # - # Detailed information about running DRb through firewalls is - # available at http://www.rubygarden.org/ruby?DrbTutorial - def activate_drb(uri = nil, allowed_hosts = ['localhost', '127.0.0.1', '::1'], - ignore_collisions = false) - - return false if @use_drb - - uri ||= 'druby://localhost:42531' - - if allowed_hosts then - acl = ["deny", "all"] - - Array(allowed_hosts).each do |host| - acl += ["allow", host] - end - - DRb.install_acl(ACL.new(acl)) - end - - @use_drb = true - @drb_service = DRbService.new - did_collision = false - begin - @service = DRb.start_service(uri, @drb_service) - rescue Errno::EADDRINUSE - if ignore_collisions then - nil - else - # The port is already occupied by another - # Breakpoint service. We will try to tell - # the old service that we want its port. - # It will then forward that request to the - # user and retry. - unless did_collision then - DRbObject.new(nil, uri).collision - did_collision = true - end - sleep(10) - retry - end - end - - return true - end - - # Deactivates a running Breakpoint service. - def deactivate_drb - @service.stop_service unless @service.nil? - @service = nil - @use_drb = false - @drb_service = nil - end - - # Returns true when Breakpoints are used over DRb. - # Breakpoint.activate_drb causes this to be true. - def use_drb? - @use_drb == true - end -end - -module IRB #:nodoc: - class << self; remove_method :start; end - def self.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 - - old_sigint = trap("SIGINT") do - begin - irb.signal_handle - rescue RubyLex::TerminateLineInput - # ignored - end - end - - catch(:IRB_EXIT) do - irb.eval_input - end - ensure - trap("SIGINT", old_sigint) - end - - class << self - alias :old_CurrentContext :CurrentContext - remove_method :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 << self - alias :old_parse_opts :parse_opts - remove_method :parse_opts - end - def IRB.parse_opts() end - - class Context #:nodoc: - alias :old_evaluate :evaluate - def evaluate(line, line_no) - if line.chomp == "exit" then - exit - else - old_evaluate(line, line_no) - end - end - end - - class WorkSpace #:nodoc: - alias :old_evaluate :evaluate - - def evaluate(*args) - if Breakpoint.use_drb? then - result = old_evaluate(*args) - if args[0] != :no_proxy and - not [true, false, nil].include?(result) - then - result.extend(DRbUndumped) rescue nil - end - return result - else - old_evaluate(*args) - end - end - end - - module InputCompletor #:nodoc: - def self.eval(code, context, *more) - # Big hack, this assumes that InputCompletor - # will only call eval() when it wants code - # to be executed in the IRB context. - IRB.conf[:MAIN_CONTEXT].workspace.evaluate(:no_proxy, code, *more) - end - end -end - -module DRb # :nodoc: - class DRbObject #:nodoc: - undef :inspect if method_defined?(:inspect) - undef :clone if method_defined?(:clone) - end -end - -# See Breakpoint.breakpoint -def breakpoint(id = nil, &block) - Binding.of_caller do |context| - Breakpoint.breakpoint(id, context, &block) - end -end - -# See Breakpoint.assert -def assert(&block) - Binding.of_caller do |context| - Breakpoint.assert(context, &block) - end -end diff --git a/activesupport/lib/active_support/core_ext/kernel.rb b/activesupport/lib/active_support/core_ext/kernel.rb index 1aa4f72b45..6475be7efa 100644 --- a/activesupport/lib/active_support/core_ext/kernel.rb +++ b/activesupport/lib/active_support/core_ext/kernel.rb @@ -2,3 +2,4 @@ require File.dirname(__FILE__) + '/kernel/reporting' require File.dirname(__FILE__) + '/kernel/agnostics' require File.dirname(__FILE__) + '/kernel/requires' +require File.dirname(__FILE__) + '/kernel/debugger' diff --git a/activesupport/lib/active_support/core_ext/kernel/debugger.rb b/activesupport/lib/active_support/core_ext/kernel/debugger.rb new file mode 100644 index 0000000000..c74d6cf884 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/kernel/debugger.rb @@ -0,0 +1,13 @@ +module Kernel + unless respond_to?(:debugger) + # Starts a debugging session if ruby-debug has been loaded (call script/server --debugger to do load it). + def debugger + RAILS_DEFAULT_LOGGER.info "\n***** Debugger requested, but was not available: Start server with --debugger to enable *****\n" + end + end + + def breakpoint + RAILS_DEFAULT_LOGGER.info "\n***** The 'breakpoint' command has been renamed 'debugger' -- please change *****\n" + debugger + end +end \ No newline at end of file diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 0e8de48952..d374c32d22 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,17 @@ *SVN* +* Removed breakpointer and Binding.of_caller in favor of relying on ruby-debug by Kent Sibilev since the breakpointer has been broken since Ruby 1.8.4 and will not be coming back [DHH] + + To use the new debugger, start your server with script/server --debugger and insert a call to 'debugger' + (instead of 'breakpoint') where you want to jump into the debugger. + + BACKWARDS INCOMPATIBILITY NOTE: You must remove the default line 12 from config/environments/development.rb: + + config.breakpoint_server = true + + This configuration option is no longer available. Rails will fail to start in development mode as long as + that's still present. + * Resource scaffolding returns the created entity.to_xml. [Jeremy Kemper] * Resource scaffolding responds to new.xml. #8185 [Eric Mill] diff --git a/railties/README b/railties/README index 7b0265321a..b0e535222e 100644 --- a/railties/README +++ b/railties/README @@ -69,29 +69,27 @@ automatically display debugging and runtime information to these files. Debuggin info will also be shown in the browser on requests from 127.0.0.1. -== Breakpoints +== Debugger -Breakpoint support is available through the script/breakpointer client. This -means that you can break out of execution at any point in the code, investigate +Debugger support is available through the debugger command when you start your Mongrel or +Webrick server with --debugger. This means that you can break out of execution at any point in the code, investigate and change the model, AND then resume execution! Example: class WeblogController < ActionController::Base def index @posts = Post.find(:all) - breakpoint "Breaking out from the list" + debugger end end So the controller will accept the action, run the first line, then present you -with a IRB prompt in the breakpointer window. Here you can do things like: - -Executing breakpoint "Breaking out from the list" at .../webrick_server.rb:16 in 'breakpoint' +with a IRB prompt in the server window. Here you can do things like: >> @posts.inspect => "[#nil, \"body\"=>nil, \"id\"=>\"1\"}>, #\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]" - >> @posts.first.title = "hello from a breakpoint" - => "hello from a breakpoint" + >> @posts.first.title = "hello from a debugger" + => "hello from a debugger" ...and even better is that you can examine how your runtime objects actually work: @@ -100,7 +98,7 @@ Executing breakpoint "Breaking out from the list" at .../webrick_server.rb:16 in >> f. Display all 152 possibilities? (y or n) -Finally, when you're ready to resume execution, you press CTRL-D +Finally, when you're ready to resume execution, you enter "cont" == Console diff --git a/railties/Rakefile b/railties/Rakefile index 4b68c3b01e..ad6590fe87 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -69,7 +69,7 @@ LOG_FILES = %w( server.log development.log test.log production.log ) HTML_FILES = %w( 404.html 500.html index.html robots.txt favicon.ico images/rails.png javascripts/prototype.js javascripts/application.js javascripts/effects.js javascripts/dragdrop.js javascripts/controls.js ) -BIN_FILES = %w( about breakpointer console destroy generate performance/benchmarker performance/profiler process/reaper process/spawner process/inspector runner server plugin ) +BIN_FILES = %w( about console destroy generate performance/benchmarker performance/profiler process/reaper process/spawner process/inspector runner server plugin ) VENDOR_LIBS = %w( actionpack activerecord actionmailer activesupport actionwebservice railties ) diff --git a/railties/bin/breakpointer b/railties/bin/breakpointer deleted file mode 100644 index 64af76edd4..0000000000 --- a/railties/bin/breakpointer +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/breakpointer' \ No newline at end of file diff --git a/railties/environments/development.rb b/railties/environments/development.rb index 0589aa979e..568ccd0cc5 100644 --- a/railties/environments/development.rb +++ b/railties/environments/development.rb @@ -8,9 +8,6 @@ # Log error messages when you accidentally call methods on nil. config.whiny_nils = true -# Enable the breakpoint server that script/breakpointer connects to -config.breakpoint_server = true - # Show full error reports and disable caching config.action_controller.consider_all_requests_local = true config.action_controller.perform_caching = false diff --git a/railties/lib/binding_of_caller.rb b/railties/lib/binding_of_caller.rb deleted file mode 100644 index c1f2cc7b4d..0000000000 --- a/railties/lib/binding_of_caller.rb +++ /dev/null @@ -1,85 +0,0 @@ -begin - require 'simplecc' -rescue LoadError - # to satisfy rdoc - class Continuation #:nodoc: - end - def Continuation.create(*args, &block) # :nodoc: - cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?} - result ||= args - return *[cc, *result] - end -end - -class Binding; end # for RDoc -# 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" then - nil - elsif type == "c-return" and extra_data[3] == :set_trace_func then - nil - else - 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 diff --git a/railties/lib/breakpoint.rb b/railties/lib/breakpoint.rb deleted file mode 100644 index a4ed787b01..0000000000 --- a/railties/lib/breakpoint.rb +++ /dev/null @@ -1,553 +0,0 @@ -# The Breakpoint library provides the convenience of -# being able to inspect and modify state, diagnose -# bugs all via IRB by simply setting breakpoints in -# your applications by the call of a method. -# -# This library was written and is supported by me, -# Florian Gross. I can be reached at flgr@ccan.de -# and enjoy getting feedback about my libraries. -# -# The whole library (including breakpoint_client.rb -# and binding_of_caller.rb) is licensed under the -# same license that Ruby uses. (Which is currently -# either the GNU General Public License or a custom -# one that allows for commercial usage.) If you for -# some good reason need to use this under another -# license please contact me. - -require 'irb' -if RUBY_VERSION == '1.8.5' - def Binding.of_caller(&block) - raise "Breakpoints are not currently working with Ruby 1.8.5" - end -else - require 'binding_of_caller' -end -require 'drb' -require 'drb/acl' - -module Breakpoint - id = %q$Id: breakpoint.rb 92 2005-02-04 22:35:53Z flgr $ - Version = id.split(" ")[2].to_i - - 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+. - # - # The source code around the location where the breakpoint - # was executed can be examined via +source_lines+. Its - # argument specifies how much lines of context to display. - # The default amount of context is 5 lines. Note that - # the call to +source_lines+ can raise an exception when - # it isn't able to read in the source code. - # - # 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(#):001:0> local_variables - # => ["name", "age", "_", "__"] - # irb(#):002:0> [name, age] - # => ["Random Person", 23] - # irb(#):003:0> [@name, @age] - # => ["Random Person", 23] - # irb(#):004:0> self - # => # - # irb(#):005:0> @age += 1; self - # => # - # irb(#):006:0> exit - # Executing break point "Person#name" at file.rb:9 in `name' - # irb(#):001:0> throw(:debug_return, "Overriden name") - # Name: Overriden name - # - # Breakpoint sessions will automatically have a few - # convenience methods available. See Breakpoint::CommandBundle - # for a list of them. - # - # Breakpoints can also be used remotely over sockets. - # This is implemented by running part of the IRB session - # in the application and part of it in a special client. - # You have to call Breakpoint.activate_drb to enable - # support for remote breakpoints and then run - # breakpoint_client.rb which is distributed with this - # library. See the documentation of Breakpoint.activate_drb - # for details. - 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, file, line, &block) - end - - Binding.of_caller do |binding_context| - handle_breakpoint(binding_context, message, file, line, &block) - end - end - - module CommandBundle - # Proxy to a Breakpoint client. Lets you directly execute code - # in the context of the client. - class Client - def initialize(eval_handler) # :nodoc: - eval_handler.untaint - @eval_handler = eval_handler - end - - instance_methods.each do |method| - next if method[/^__.+__$/] - undef_method method - end - - # Executes the specified code at the client. - def eval(code) - @eval_handler.call(code) - end - - # Will execute the specified statement at the client. - def method_missing(method, *args, &block) - if args.empty? and not block - result = eval "#{method}" - else - # This is a bit ugly. The alternative would be using an - # eval context instead of an eval handler for executing - # the code at the client. The problem with that approach - # is that we would have to handle special expressions - # like "self", "nil" or constants ourself which is hard. - remote = eval %{ - result = lambda { |block, *args| #{method}(*args, &block) } - def result.call_with_block(*args, &block) - call(block, *args) - end - result - } - remote.call_with_block(*args, &block) - end - - return result - end - end - - # Returns the source code surrounding the location where the - # breakpoint was issued. - def source_lines(context = 5, return_line_numbers = false) - lines = File.readlines(@__bp_file).map { |line| line.chomp } - - break_line = @__bp_line - start_line = [break_line - context, 1].max - end_line = break_line + context - - result = lines[(start_line - 1) .. (end_line - 1)] - - if return_line_numbers then - return [start_line, break_line, result] - else - return result - end - end - - # Prints the source code surrounding the location where the - # breakpoint was issued. - def show_source_list(context = 5) - start_line, break_line, result = source_lines(context, true) - offset = [(break_line + context).to_s.length, 4].max - result.each_with_index do |line, i| - mark = (start_line + i == break_line ? '->' : ' ') - client.puts("%0#{offset}d%s#{line}" % [start_line + i, mark]) - end - Pathname.new(@__bp_file).cleanpath.to_s - end - - # Prints the call stack. - def show_call_stack(depth = 10) - base = Pathname.new(RAILS_ROOT).cleanpath.to_s - caller[1..depth].each do |line| - line.sub!(/^[^:]*/) do |path| - Pathname.new(path).cleanpath.to_s - end - client.puts(line.index(base) == 0 ? line[(base.length + 1)..-1] : line) - end - "#{Pathname.new(@__bp_file).cleanpath.to_s}:#{@__bp_line}" - end - - # Lets an object that will forward method calls to the breakpoint - # client. This is useful for outputting longer things at the client - # and so on. You can for example do these things: - # - # client.puts "Hello" # outputs "Hello" at client console - # # outputs "Hello" into the file temp.txt at the client - # client.File.open("temp.txt", "w") { |f| f.puts "Hello" } - def client() - if Breakpoint.use_drb? then - sleep(0.5) until Breakpoint.drb_service.eval_handler - Client.new(Breakpoint.drb_service.eval_handler) - else - Client.new(lambda { |code| eval(code, TOPLEVEL_BINDING) }) - end - end - end - - def handle_breakpoint(context, message, file = "", line = "", &block) # :nodoc: - catch(:debug_return) do |value| - eval(%{ - @__bp_file = #{file.inspect} - @__bp_line = #{line} - extend Breakpoint::CommandBundle - extend DRbUndumped if self - }, context) rescue nil - - 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 - - # These exceptions will be raised on failed asserts - # if Breakpoint.asserts_cause_exceptions is set to - # true. - class FailedAssertError < RuntimeError - end - - # 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 in production - # code by setting Breakpoint.optimize_asserts to - # true. (It will still be enabled when Ruby is run - # via the -d argument.) - # - # Example: - # person_name = "Foobar" - # assert { not person_name.nil? } - # - # Note: If you want to use this method from an - # unit test, you will have to call it by its full - # name, Breakpoint.assert. - 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}." - - if Breakpoint.asserts_cause_exceptions and not $DEBUG then - raise(Breakpoint::FailedAssertError, message) - end - - message += " Executing implicit breakpoint." - - if context then - return handle_breakpoint(context, message, file, line) - end - - Binding.of_caller do |context| - handle_breakpoint(context, message, file, line) - 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 :optimize_asserts - self.optimize_asserts = false - - # Whether an Exception should be raised on failed asserts - # in non-$DEBUG code or not. By default this is disabled. - attr_accessor :asserts_cause_exceptions - self.asserts_cause_exceptions = false - @use_drb = false - - attr_reader :drb_service # :nodoc: - - class DRbService # :nodoc: - include DRbUndumped - - def initialize - @handler = @eval_handler = @collision_handler = nil - - IRB.instance_eval { @CONF[:RC] = true } - IRB.run_config - end - - def collision - sleep(0.5) until @collision_handler - - @collision_handler.untaint - - @collision_handler.call - end - - def ping() end - - def add_breakpoint(context, message) - workspace = IRB::WorkSpace.new(context) - workspace.extend(DRbUndumped) - - sleep(0.5) until @handler - - @handler.untaint - @handler.call(workspace, message) - end - - attr_accessor :handler, :eval_handler, :collision_handler - end - - # Will run Breakpoint in DRb mode. This will spawn a server - # that can be attached to via the breakpoint-client 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.) - # - # Also note that by default this will only allow access - # from localhost. You can however specify a list of - # allowed hosts or nil (to allow access from everywhere). - # But that will still not protect you from somebody - # reading the data as it goes through the net. - # - # A good approach for getting security and remote access - # is setting up an SSH tunnel between the DRb service - # and the client. This is usually done like this: - # - # $ ssh -L20000:127.0.0.1:20000 -R10000:127.0.0.1:10000 example.com - # (This will connect port 20000 at the client side to port - # 20000 at the server side, and port 10000 at the server - # side to port 10000 at the client side.) - # - # After that do this on the server side: (the code being debugged) - # Breakpoint.activate_drb("druby://127.0.0.1:20000", "localhost") - # - # And at the client side: - # ruby breakpoint_client.rb -c druby://127.0.0.1:10000 -s druby://127.0.0.1:20000 - # - # Running through such a SSH proxy will also let you use - # breakpoint.rb in case you are behind a firewall. - # - # Detailed information about running DRb through firewalls is - # available at http://www.rubygarden.org/ruby?DrbTutorial - def activate_drb(uri = nil, allowed_hosts = ['localhost', '127.0.0.1', '::1'], - ignore_collisions = false) - - return false if @use_drb - - uri ||= 'druby://localhost:42531' - - if allowed_hosts then - acl = ["deny", "all"] - - Array(allowed_hosts).each do |host| - acl += ["allow", host] - end - - DRb.install_acl(ACL.new(acl)) - end - - @use_drb = true - @drb_service = DRbService.new - did_collision = false - begin - @service = DRb.start_service(uri, @drb_service) - rescue Errno::EADDRINUSE - if ignore_collisions then - nil - else - # The port is already occupied by another - # Breakpoint service. We will try to tell - # the old service that we want its port. - # It will then forward that request to the - # user and retry. - unless did_collision then - DRbObject.new(nil, uri).collision - did_collision = true - end - sleep(10) - retry - end - end - - return true - end - - # Deactivates a running Breakpoint service. - def deactivate_drb - @service.stop_service unless @service.nil? - @service = nil - @use_drb = false - @drb_service = nil - end - - # Returns true when Breakpoints are used over DRb. - # Breakpoint.activate_drb causes this to be true. - def use_drb? - @use_drb == true - end -end - -module IRB # :nodoc: - class << self; remove_method :start; end - def self.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 - - old_sigint = trap("SIGINT") do - begin - irb.signal_handle - rescue RubyLex::TerminateLineInput - # ignored - end - end - - catch(:IRB_EXIT) do - irb.eval_input - end - ensure - trap("SIGINT", old_sigint) - end - - class << self - alias :old_CurrentContext :CurrentContext - remove_method :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 - def IRB.parse_opts() end - - class Context #:nodoc: - alias :old_evaluate :evaluate - def evaluate(line, line_no) - if line.chomp == "exit" then - exit - else - old_evaluate(line, line_no) - end - end - end - - class WorkSpace #:nodoc: - alias :old_evaluate :evaluate - - def evaluate(*args) - if Breakpoint.use_drb? then - result = old_evaluate(*args) - if args[0] != :no_proxy and - not [true, false, nil].include?(result) - then - result.extend(DRbUndumped) rescue nil - end - return result - else - old_evaluate(*args) - end - end - end - - module InputCompletor #:nodoc: - def self.eval(code, context, *more) - # Big hack, this assumes that InputCompletor - # will only call eval() when it wants code - # to be executed in the IRB context. - IRB.conf[:MAIN_CONTEXT].workspace.evaluate(:no_proxy, code, *more) - end - end -end - -module DRb #:nodoc: - class DRbObject #:nodoc: - undef :inspect if method_defined?(:inspect) - undef :clone if method_defined?(:clone) - end -end - -# See Breakpoint.breakpoint -def breakpoint(id = nil, &block) - Binding.of_caller do |context| - Breakpoint.breakpoint(id, context, &block) - end -end - -# See Breakpoint.assert -def assert(&block) - Binding.of_caller do |context| - Breakpoint.assert(context, &block) - end -end diff --git a/railties/lib/breakpoint_client.rb b/railties/lib/breakpoint_client.rb deleted file mode 100644 index 9273321599..0000000000 --- a/railties/lib/breakpoint_client.rb +++ /dev/null @@ -1,196 +0,0 @@ -require 'breakpoint' -require 'optparse' -require 'timeout' - -Options = { - :ClientURI => nil, - :ServerURI => "druby://localhost:42531", - :RetryDelay => 2, - :Permanent => true, - :Verbose => false -} - -ARGV.options do |opts| - script_name = File.basename($0) - opts.banner = [ - "Usage: ruby #{script_name} [Options] [server uri]", - "", - "This tool lets you connect to a breakpoint service ", - "which was started via Breakpoint.activate_drb.", - "", - "The server uri defaults to druby://localhost:42531" - ].join("\n") - - opts.separator "" - - opts.on("-c", "--client-uri=uri", - "Run the client on the specified uri.", - "This can be used to specify the port", - "that the client uses to allow for back", - "connections from the server.", - "Default: Find a good URI automatically.", - "Example: -c druby://localhost:12345" - ) { |v| Options[:ClientURI] = v } - - opts.on("-s", "--server-uri=uri", - "Connect to the server specified at the", - "specified uri.", - "Default: druby://localhost:42531" - ) { |v| Options[:ServerURI] = v } - - opts.on("-R", "--retry-delay=delay", Integer, - "Automatically try to reconnect to the", - "server after delay seconds when the", - "connection failed or timed out.", - "A value of 0 disables automatical", - "reconnecting completely.", - "Default: 10" - ) { |v| Options[:RetryDelay] = v } - - opts.on("-P", "--[no-]permanent", - "Run the breakpoint client in permanent mode.", - "This means that the client will keep continue", - "running even after the server has closed the", - "connection. Useful for example in Rails." - ) { |v| Options[:Permanent] = v } - - opts.on("-V", "--[no-]verbose", - "Run the breakpoint client in verbose mode.", - "Will produce more messages, for example between", - "individual breakpoints. This might help in seeing", - "that the breakpoint client is still alive, but adds", - "quite a bit of clutter." - ) { |v| Options[:Verbose] = v } - - opts.separator "" - - opts.on("-h", "--help", - "Show this help message." - ) { puts opts; exit } - opts.on("-v", "--version", - "Display the version information." - ) do - id = %q$Id: breakpoint_client.rb 91 2005-02-04 22:34:08Z flgr $ - puts id.sub("Id: ", "") - puts "(Breakpoint::Version = #{Breakpoint::Version})" - exit - end - - opts.parse! -end - -Options[:ServerURI] = ARGV[0] if ARGV[0] - -module Handlers #:nodoc: - extend self - - def breakpoint_handler(workspace, message) - puts message - IRB.start(nil, nil, workspace) - - puts "" - if Options[:Verbose] then - puts "Resumed execution. Waiting for next breakpoint...", "" - end - end - - def eval_handler(code) - result = eval(code, TOPLEVEL_BINDING) - if result then - DRbObject.new(result) - else - result - end - end - - def collision_handler() - 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 - end -end - -# Used for checking whether we are currently in the reconnecting loop. -reconnecting = false - -loop do - DRb.start_service(Options[:ClientURI]) - - begin - service = DRbObject.new(nil, Options[:ServerURI]) - - begin - ehandler = Handlers.method(:eval_handler) - chandler = Handlers.method(:collision_handler) - handler = Handlers.method(:breakpoint_handler) - service.eval_handler = ehandler - service.collision_handler = chandler - service.handler = handler - - reconnecting = false - if Options[:Verbose] then - puts "Connection established. Waiting for breakpoint...", "" - end - - loop do - begin - service.ping - rescue DRb::DRbConnError => error - puts "Server exited. Closing connection...", "" - exit! unless Options[:Permanent] - break - end - - sleep(0.5) - end - ensure - service.eval_handler = nil - service.collision_handler = nil - service.handler = nil - end - rescue Exception => error - if Options[:RetryDelay] > 0 then - if not reconnecting then - reconnecting = true - puts "No connection to breakpoint service at #{Options[:ServerURI]} " + - "(#{error.class})" - puts error.backtrace if $DEBUG - puts "Tries to connect will be made every #{Options[:RetryDelay]} seconds..." - end - - sleep Options[:RetryDelay] - retry - else - raise - end - end -end diff --git a/railties/lib/commands/breakpointer.rb b/railties/lib/commands/breakpointer.rb deleted file mode 100644 index cc52010c32..0000000000 --- a/railties/lib/commands/breakpointer.rb +++ /dev/null @@ -1 +0,0 @@ -require 'breakpoint_client' diff --git a/railties/lib/commands/servers/base.rb b/railties/lib/commands/servers/base.rb index 25b2935524..ed32c3eea5 100644 --- a/railties/lib/commands/servers/base.rb +++ b/railties/lib/commands/servers/base.rb @@ -17,3 +17,15 @@ def tail(log_file) end tail_thread end + +def start_debugger + begin + require_library_or_gem 'ruby-debug' + Debugger.start + # Debugger.settings[:autoirb] = true + puts "=> Debugger enabled" + rescue Exception + puts "You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'" + exit + end +end \ No newline at end of file diff --git a/railties/lib/commands/servers/mongrel.rb b/railties/lib/commands/servers/mongrel.rb index 995274f9a0..5eb14bce1e 100644 --- a/railties/lib/commands/servers/mongrel.rb +++ b/railties/lib/commands/servers/mongrel.rb @@ -12,13 +12,15 @@ :port => 3000, :ip => "0.0.0.0", :environment => (ENV['RAILS_ENV'] || "development").dup, - :detach => false + :detach => false, + :debugger => false } ARGV.clone.options do |opts| opts.on("-p", "--port=port", Integer, "Runs Rails on the specified port.", "Default: 3000") { |v| OPTIONS[:port] = v } opts.on("-b", "--binding=ip", String, "Binds Rails to the specified ip.", "Default: 0.0.0.0") { |v| OPTIONS[:ip] = v } opts.on("-d", "--daemon", "Make server run as a Daemon.") { OPTIONS[:detach] = true } + opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { OPTIONS[:debugger] = true } opts.on("-e", "--environment=name", String, "Specifies the environment to run this server under (test/development/production).", "Default: development") { |v| OPTIONS[:environment] = v } @@ -46,6 +48,8 @@ ENV["RAILS_ENV"] = OPTIONS[:environment] RAILS_ENV.replace(OPTIONS[:environment]) if defined?(RAILS_ENV) + start_debugger if OPTIONS[:debugger] + require 'initializer' Rails::Initializer.run(:initialize_logger) diff --git a/railties/lib/commands/servers/webrick.rb b/railties/lib/commands/servers/webrick.rb index 3fddcc5459..0f06560457 100644 --- a/railties/lib/commands/servers/webrick.rb +++ b/railties/lib/commands/servers/webrick.rb @@ -2,13 +2,15 @@ require 'optparse' OPTIONS = { - :port => 3000, - :ip => "0.0.0.0", - :environment => (ENV['RAILS_ENV'] || "development").dup, - :server_root => File.expand_path(RAILS_ROOT + "/public/"), - :server_type => WEBrick::SimpleServer, - :charset => "UTF-8", - :mime_types => WEBrick::HTTPUtils::DefaultMimeTypes + :port => 3000, + :ip => "0.0.0.0", + :environment => (ENV['RAILS_ENV'] || "development").dup, + :server_root => File.expand_path(RAILS_ROOT + "/public/"), + :server_type => WEBrick::SimpleServer, + :charset => "UTF-8", + :mime_types => WEBrick::HTTPUtils::DefaultMimeTypes, + :debugger => false + } ARGV.options do |opts| @@ -34,6 +36,8 @@ "Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)." ) { OPTIONS[:server_type] = WEBrick::Daemon } + opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { OPTIONS[:debugger] = true } + opts.on("-c", "--charset=charset", String, "Set default charset for output.", "Default: UTF-8") { |v| OPTIONS[:charset] = v } @@ -46,6 +50,8 @@ opts.parse! end +start_debugger if OPTIONS[:debugger] + ENV["RAILS_ENV"] = OPTIONS[:environment] RAILS_ENV.replace(OPTIONS[:environment]) if defined?(RAILS_ENV) diff --git a/railties/lib/dispatcher.rb b/railties/lib/dispatcher.rb index 7ed3426832..1a6557b971 100644 --- a/railties/lib/dispatcher.rb +++ b/railties/lib/dispatcher.rb @@ -104,7 +104,6 @@ def prepare_application self.preparation_callbacks_run = false end - prepare_breakpoint require_dependency 'application' unless Object.const_defined?(:ApplicationController) ActiveRecord::Base.verify_active_connections! if defined?(ActiveRecord) run_preparation_callbacks @@ -112,16 +111,6 @@ def prepare_application def reset_after_dispatch reset_application! if Dependencies.load? - Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT) - end - - def prepare_breakpoint - return unless defined?(BREAKPOINT_SERVER_PORT) - require 'breakpoint' - Breakpoint.activate_drb("druby://localhost:#{BREAKPOINT_SERVER_PORT}", nil, !defined?(FastCGI)) - true - rescue - nil end def run_preparation_callbacks diff --git a/railties/lib/fcgi_handler.rb b/railties/lib/fcgi_handler.rb index d7e95b8fbe..85e5ca99b3 100644 --- a/railties/lib/fcgi_handler.rb +++ b/railties/lib/fcgi_handler.rb @@ -9,8 +9,7 @@ class RailsFCGIHandler 'INT' => :exit_now, 'TERM' => :exit_now, 'USR1' => :exit, - 'USR2' => :restart, - 'SIGTRAP' => :breakpoint + 'USR2' => :restart } GLOBAL_SIGNALS = SIGNALS.keys - %w(USR1) @@ -131,11 +130,6 @@ def restart_handler(signal) @when_ready = :restart end - def breakpoint_handler(signal) - dispatcher_log :info, "asked to breakpoint ASAP" - @when_ready = :breakpoint - end - def process_each_request!(provider) cgi = nil provider.each_cgi do |cgi| @@ -152,9 +146,6 @@ def process_each_request!(provider) when :exit close_connection(cgi) break - when :breakpoint - close_connection(cgi) - breakpoint! end gc_countdown @@ -198,15 +189,6 @@ def restore! ActionController::Routing::Routes.reload end - def breakpoint! - require 'breakpoint' - port = defined?(BREAKPOINT_SERVER_PORT) ? BREAKPOINT_SERVER_PORT : 42531 - Breakpoint.activate_drb("druby://localhost:#{port}", nil, !defined?(FastCGI)) - dispatcher_log :info, "breakpointing" - breakpoint - @when_ready = nil - end - def run_gc! @gc_request_countdown = gc_request_period GC.enable; GC.start; GC.disable diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 577a3c88f1..11e24c503b 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -69,7 +69,6 @@ def initialize(configuration) # * #initialize_framework_logging # * #initialize_framework_views # * #initialize_dependency_mechanism - # * #initialize_breakpoints # * #initialize_whiny_nils # * #initialize_framework_settings # * #load_environment @@ -98,7 +97,6 @@ def process initialize_framework_logging initialize_framework_views initialize_dependency_mechanism - initialize_breakpoints initialize_whiny_nils initialize_temporary_directories initialize_framework_settings @@ -298,12 +296,6 @@ def initialize_dependency_mechanism Dependencies.mechanism = configuration.cache_classes ? :require : :load end - # Sets the +BREAKPOINT_SERVER_PORT+ if Configuration#breakpoint_server - # is true. - def initialize_breakpoints - silence_warnings { Object.const_set("BREAKPOINT_SERVER_PORT", 42531) if configuration.breakpoint_server } - end - # Loads support for "whiny nil" (noisy warnings when methods are invoked # on +nil+ values) if Configuration#whiny_nils is true. def initialize_whiny_nils @@ -385,9 +377,6 @@ class Configuration # A stub for setting options on ActiveRecord::Base attr_accessor :active_resource - # Whether or not to use the breakpoint server (boolean) - attr_accessor :breakpoint_server - # Whether or not classes should be cached (set to false if you want # application classes to be reloaded on each request) attr_accessor :cache_classes @@ -474,7 +463,6 @@ def initialize self.view_path = default_view_path self.controller_paths = default_controller_paths self.cache_classes = default_cache_classes - self.breakpoint_server = default_breakpoint_server self.whiny_nils = default_whiny_nils self.plugins = default_plugins self.plugin_paths = default_plugin_paths @@ -634,10 +622,6 @@ def default_cache_classes false end - def default_breakpoint_server - false - end - def default_whiny_nils false end diff --git a/railties/lib/rails_generator/generators/applications/app/app_generator.rb b/railties/lib/rails_generator/generators/applications/app/app_generator.rb index 6c93fe14f8..1ac5b27300 100644 --- a/railties/lib/rails_generator/generators/applications/app/app_generator.rb +++ b/railties/lib/rails_generator/generators/applications/app/app_generator.rb @@ -67,7 +67,7 @@ def manifest m.file "environments/test.rb", "config/environments/test.rb" # Scripts - %w( about breakpointer console destroy generate performance/benchmarker performance/profiler process/reaper process/spawner process/inspector runner server plugin ).each do |file| + %w( about console destroy generate performance/benchmarker performance/profiler process/reaper process/spawner process/inspector runner server plugin ).each do |file| m.file "bin/#{file}", "script/#{file}", script_options end diff --git a/railties/lib/test_help.rb b/railties/lib/test_help.rb index a5201cba6d..61f64972c4 100644 --- a/railties/lib/test_help.rb +++ b/railties/lib/test_help.rb @@ -8,7 +8,6 @@ require 'active_record/fixtures' require 'action_controller/test_process' require 'action_controller/integration' -require 'breakpoint' Test::Unit::TestCase.fixture_path = RAILS_ROOT + "/test/fixtures/" ActionController::IntegrationTest.fixture_path = Test::Unit::TestCase.fixture_path diff --git a/railties/test/fcgi_dispatcher_test.rb b/railties/test/fcgi_dispatcher_test.rb index 7e9adbe9d3..607e15d912 100644 --- a/railties/test/fcgi_dispatcher_test.rb +++ b/railties/test/fcgi_dispatcher_test.rb @@ -12,7 +12,6 @@ # Stubs require 'fcgi_handler' require 'routes' -require 'stubbed_breakpoint' require 'stubbed_kernel' class RailsFCGIHandler @@ -35,9 +34,6 @@ def send_signal(which) @signal_handlers[which].call(which) end - def breakpoint - end - alias_method :old_run_gc!, :run_gc! def run_gc! @gc_runs ||= 0 @@ -71,14 +67,6 @@ def test_process_exit @handler.process! end - def test_process_breakpoint - @handler.stubs(:when_ready).returns(:breakpoint) - - @handler.expects(:close_connection) - @handler.expects(:breakpoint!) - @handler.process! - end - def test_process_with_system_exit_exception @handler.stubs(:process_request).raises(SystemExit) @@ -93,13 +81,6 @@ def test_restart_handler assert_equal :restart, @handler.when_ready end - def test_breakpoint_handler - @handler.expects(:dispatcher_log).with(:info, "asked to breakpoint ASAP") - - @handler.send(:breakpoint_handler, nil) - assert_equal :breakpoint, @handler.when_ready - end - def test_install_signal_handler_should_log_on_bad_signal @handler.stubs(:trap).raises(ArgumentError) @@ -143,15 +124,6 @@ def test_restore! @handler.send(:restore!) end - def test_breakpoint! - @handler.expects(:require).with('breakpoint') - Breakpoint.expects(:activate_drb) - @handler.expects(:breakpoint) - @handler.expects(:dispatcher_log).with(:info, "breakpointing") - @handler.send(:breakpoint!) - assert_nil @handler.when_ready - end - def test_uninterrupted_processing @handler.process! assert_nil @handler.exit_code -- GitLab