diff options
Diffstat (limited to 'trace_point.rb')
-rw-r--r-- | trace_point.rb | 105 |
1 files changed, 87 insertions, 18 deletions
diff --git a/trace_point.rb b/trace_point.rb index 4272448682..b136e9b399 100644 --- a/trace_point.rb +++ b/trace_point.rb @@ -1,7 +1,5 @@ # loaded from vm_trace.c -# Document-class: TracePoint -# # A class that provides the functionality of Kernel#set_trace_func in a # nice Object-Oriented API. # @@ -39,8 +37,11 @@ # +:c_call+:: call a C-language routine # +:c_return+:: return from a C-language routine # +:raise+:: raise an exception +# +:rescue+:: rescue an exception # +:b_call+:: event hook at block entry # +:b_return+:: event hook at block ending +# +:a_call+:: event hook at all calls (+call+, +b_call+, and +c_call+) +# +:a_return+:: event hook at all returns (+return+, +b_return+, and +c_return+) # +:thread_begin+:: event hook at thread beginning # +:thread_end+:: event hook at thread ending # +:fiber_switch+:: event hook at fiber switch @@ -93,6 +94,7 @@ class TracePoint # Access from other threads is also forbidden. # def self.new(*events) + Primitive.attr! :use_block Primitive.tracepoint_new_s(events) end @@ -118,13 +120,11 @@ class TracePoint Primitive.tracepoint_stat_s end - # Document-method: trace - # # call-seq: - # TracePoint.trace(*events) { |obj| block } -> obj + # TracePoint.trace(*events) { |obj| block } -> obj # - # A convenience method for TracePoint.new, that activates the trace - # automatically. + # A convenience method for TracePoint.new, that activates the trace + # automatically. # # trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] } # #=> #<TracePoint:enabled> @@ -132,12 +132,79 @@ class TracePoint # trace.enabled? #=> true # def self.trace(*events) + Primitive.attr! :use_block Primitive.tracepoint_trace_s(events) end # call-seq: + # TracePoint.allow_reentry { block } + # + # In general, while a TracePoint callback is running, + # other registered callbacks are not called to avoid + # confusion by reentrance. + # This method allows the reentrance in a given block. + # This method should be used carefully, otherwise the callback + # can be easily called infinitely. + # + # If this method is called when the reentrance is already allowed, + # it raises a RuntimeError. + # + # <b>Example:</b> + # + # # Without reentry + # # --------------- + # + # line_handler = TracePoint.new(:line) do |tp| + # next if tp.path != __FILE__ # only work in this file + # puts "Line handler" + # binding.eval("class C; end") + # end.enable + # + # class_handler = TracePoint.new(:class) do |tp| + # puts "Class handler" + # end.enable + # + # class B + # end + # + # # This script will print "Class handler" only once: when inside :line + # # handler, all other handlers are ignored + # + # + # # With reentry + # # ------------ + # + # line_handler = TracePoint.new(:line) do |tp| + # next if tp.path != __FILE__ # only work in this file + # next if (__LINE__..__LINE__+3).cover?(tp.lineno) # don't be invoked from itself + # puts "Line handler" + # TracePoint.allow_reentry { binding.eval("class C; end") } + # end.enable + # + # class_handler = TracePoint.new(:class) do |tp| + # puts "Class handler" + # end.enable + # + # class B + # end + # + # # This wil print "Class handler" twice: inside allow_reentry block in :line + # # handler, other handlers are enabled. + # + # Note that the example shows the principal effect of the method, but its + # practical usage is for debugging libraries that sometimes require other libraries + # hooks to not be affected by debugger being inside trace point handling. Precautions + # should be taken against infinite recursion in this case (note that we needed to filter + # out calls by itself from :line handler, otherwise it will call itself infinitely). + # + def self.allow_reentry + Primitive.attr! :use_block + Primitive.tracepoint_allow_reentry + end + + # call-seq: # trace.enable(target: nil, target_line: nil, target_thread: nil) -> true or false - # trace.enable(target: nil, target_line: nil, target_thread: nil) { block } -> obj + # trace.enable(target: nil, target_line: nil, target_thread: :default) { block } -> obj # # Activates the trace. # @@ -151,15 +218,16 @@ class TracePoint # trace.enable #=> true (previous state) # # trace is still enabled # - # If a block is given, the trace will only be enabled within the scope of the - # block. + # If a block is given, the trace will only be enabled during the block call. + # If target and target_line are both nil, then target_thread will default + # to the current thread if a block is given. # # trace.enabled? # #=> false # # trace.enable do # trace.enabled? - # # only enabled for this block + # # only enabled for this block and thread # end # # trace.enabled? @@ -192,7 +260,8 @@ class TracePoint # trace.enable { p tp.lineno } # #=> RuntimeError: access from outside # - def enable(target: nil, target_line: nil, target_thread: nil) + def enable(target: nil, target_line: nil, target_thread: :default) + Primitive.attr! :use_block Primitive.tracepoint_enable_m(target, target_line, target_thread) end @@ -229,6 +298,7 @@ class TracePoint # trace.disable { p tp.lineno } # #=> RuntimeError: access from outside def disable + Primitive.attr! :use_block Primitive.tracepoint_disable_m end @@ -311,9 +381,8 @@ class TracePoint # Return the generated binding object from event. # - # Note that for +c_call+ and +c_return+ events, the binding returned is the - # binding of the nearest Ruby method calling the C method, since C methods - # themselves do not have bindings. + # Note that for +:c_call+ and +:c_return+ events, the method will return + # +nil+, since C methods themselves do not have bindings. def binding Primitive.tracepoint_attr_binding end @@ -321,19 +390,19 @@ class TracePoint # Return the trace object during event # # Same as the following, except it returns the correct object (the method - # receiver) for +c_call+ and +c_return+ events: + # receiver) for +:c_call+ and +:c_return+ events: # # trace.binding.eval('self') def self Primitive.tracepoint_attr_self end - # Return value from +:return+, +c_return+, and +b_return+ event + # Return value from +:return+, +:c_return+, and +:b_return+ event def return_value Primitive.tracepoint_attr_return_value end - # Value from exception raised on the +:raise+ event + # Value from exception raised on the +:raise+ event, or rescued on the +:rescue+ event. def raised_exception Primitive.tracepoint_attr_raised_exception end |