summaryrefslogtreecommitdiff
path: root/trace_point.rb
diff options
context:
space:
mode:
Diffstat (limited to 'trace_point.rb')
-rw-r--r--trace_point.rb105
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