1 # loaded from vm_trace.c
3 # A class that provides the functionality of Kernel#set_trace_func in a
4 # nice Object-Oriented API.
8 # We can use TracePoint to gather information specifically for exceptions:
10 # trace = TracePoint.new(:raise) do |tp|
11 # p [tp.lineno, tp.event, tp.raised_exception]
13 # #=> #<TracePoint:disabled>
19 # #=> [5, :raise, #<ZeroDivisionError: divided by 0>]
23 # If you don't specify the type of events you want to listen for,
24 # TracePoint will include all available events.
26 # *Note* do not depend on current event set, as this list is subject to
27 # change. Instead, it is recommended you specify the type of events you
30 # To filter what is traced, you can pass any of the following as +events+:
32 # +:line+:: execute an expression or statement on a new line
33 # +:class+:: start a class or module definition
34 # +:end+:: finish a class or module definition
35 # +:call+:: call a Ruby method
36 # +:return+:: return from a Ruby method
37 # +:c_call+:: call a C-language routine
38 # +:c_return+:: return from a C-language routine
39 # +:raise+:: raise an exception
40 # +:rescue+:: rescue an exception
41 # +:b_call+:: event hook at block entry
42 # +:b_return+:: event hook at block ending
43 # +:a_call+:: event hook at all calls (+call+, +b_call+, and +c_call+)
44 # +:a_return+:: event hook at all returns (+return+, +b_return+, and +c_return+)
45 # +:thread_begin+:: event hook at thread beginning
46 # +:thread_end+:: event hook at thread ending
47 # +:fiber_switch+:: event hook at fiber switch
48 # +:script_compiled+:: new Ruby code compiled (with +eval+, +load+ or +require+)
52 # TracePoint.new(*events) { |obj| block } -> obj
54 # Returns a new TracePoint object, not enabled by default.
56 # Next, in order to activate the trace, you must use TracePoint#enable
58 # trace = TracePoint.new(:call) do |tp|
59 # p [tp.lineno, tp.defined_class, tp.method_id, tp.event]
61 # #=> #<TracePoint:disabled>
66 # puts "Hello, TracePoint!"
68 # # [48, IRB::Notifier::AbstractNotifier, :printf, :call]
71 # When you want to deactivate the trace, you must use TracePoint#disable
75 # See TracePoint@Events for possible events and more information.
77 # A block must be given, otherwise an ArgumentError is raised.
79 # If the trace method isn't included in the given events filter, a
80 # RuntimeError is raised.
82 # TracePoint.trace(:line) do |tp|
83 # p tp.raised_exception
85 # #=> RuntimeError: 'raised_exception' not supported by this event
87 # If the trace method is called outside block, a RuntimeError is raised.
89 # TracePoint.trace(:line) do |tp|
92 # $tp.lineno #=> access from outside (RuntimeError)
94 # Access from other threads is also forbidden.
97 Primitive.attr! :use_block
98 Primitive.tracepoint_new_s(events)
102 # trace.inspect -> string
104 # Return a string containing a human-readable TracePoint
107 Primitive.tracepoint_inspect
111 # TracePoint.stat -> obj
113 # Returns internal information of TracePoint.
115 # The contents of the returned value are implementation specific.
116 # It may be changed in future.
118 # This method is only for debugging TracePoint itself.
120 Primitive.tracepoint_stat_s
124 # TracePoint.trace(*events) { |obj| block } -> obj
126 # A convenience method for TracePoint.new, that activates the trace
129 # trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] }
130 # #=> #<TracePoint:enabled>
132 # trace.enabled? #=> true
134 def self.trace(*events)
135 Primitive.attr! :use_block
136 Primitive.tracepoint_trace_s(events)
140 # TracePoint.allow_reentry { block }
142 # In general, while a TracePoint callback is running,
143 # other registered callbacks are not called to avoid
144 # confusion by reentrance.
145 # This method allows the reentrance in a given block.
146 # This method should be used carefully, otherwise the callback
147 # can be easily called infinitely.
149 # If this method is called when the reentrance is already allowed,
150 # it raises a RuntimeError.
157 # line_handler = TracePoint.new(:line) do |tp|
158 # next if tp.path != __FILE__ # only work in this file
159 # puts "Line handler"
160 # binding.eval("class C; end")
163 # class_handler = TracePoint.new(:class) do |tp|
164 # puts "Class handler"
170 # # This script will print "Class handler" only once: when inside :line
171 # # handler, all other handlers are ignored
177 # line_handler = TracePoint.new(:line) do |tp|
178 # next if tp.path != __FILE__ # only work in this file
179 # next if (__LINE__..__LINE__+3).cover?(tp.lineno) # don't be invoked from itself
180 # puts "Line handler"
181 # TracePoint.allow_reentry { binding.eval("class C; end") }
184 # class_handler = TracePoint.new(:class) do |tp|
185 # puts "Class handler"
191 # # This wil print "Class handler" twice: inside allow_reentry block in :line
192 # # handler, other handlers are enabled.
194 # Note that the example shows the principal effect of the method, but its
195 # practical usage is for debugging libraries that sometimes require other libraries
196 # hooks to not be affected by debugger being inside trace point handling. Precautions
197 # should be taken against infinite recursion in this case (note that we needed to filter
198 # out calls by itself from :line handler, otherwise it will call itself infinitely).
200 def self.allow_reentry
201 Primitive.attr! :use_block
202 Primitive.tracepoint_allow_reentry
206 # trace.enable(target: nil, target_line: nil, target_thread: nil) -> true or false
207 # trace.enable(target: nil, target_line: nil, target_thread: :default) { block } -> obj
209 # Activates the trace.
211 # Returns +true+ if trace was enabled.
212 # Returns +false+ if trace was disabled.
214 # trace.enabled? #=> false
215 # trace.enable #=> false (previous state)
217 # trace.enabled? #=> true
218 # trace.enable #=> true (previous state)
219 # # trace is still enabled
221 # If a block is given, the trace will only be enabled during the block call.
222 # If target and target_line are both nil, then target_thread will default
223 # to the current thread if a block is given.
230 # # only enabled for this block and thread
236 # +target+, +target_line+ and +target_thread+ parameters are used to
237 # limit tracing only to specified code objects. +target+ should be a
238 # code object for which RubyVM::InstructionSequence.of will return
239 # an instruction sequence.
241 # t = TracePoint.new(:line) { |tp| p tp }
251 # t.enable(target: method(:m1))
254 # # prints #<TracePoint:line test.rb:4 in `m1'>
258 # Note: You cannot access event hooks within the +enable+ block.
260 # trace.enable { p tp.lineno }
261 # #=> RuntimeError: access from outside
263 def enable(target: nil, target_line: nil, target_thread: :default)
264 Primitive.attr! :use_block
265 Primitive.tracepoint_enable_m(target, target_line, target_thread)
269 # trace.disable -> true or false
270 # trace.disable { block } -> obj
272 # Deactivates the trace
274 # Return true if trace was enabled.
275 # Return false if trace was disabled.
277 # trace.enabled? #=> true
278 # trace.disable #=> true (previous status)
279 # trace.enabled? #=> false
280 # trace.disable #=> false
282 # If a block is given, the trace will only be disable within the scope of the
290 # # only disabled for this block
296 # Note: You cannot access event hooks within the block.
298 # trace.disable { p tp.lineno }
299 # #=> RuntimeError: access from outside
301 Primitive.attr! :use_block
302 Primitive.tracepoint_disable_m
306 # trace.enabled? -> true or false
308 # The current status of the trace
310 Primitive.tracepoint_enabled_p
315 # See TracePoint@Events for more information.
317 Primitive.tracepoint_attr_event
320 # Line number of the event
322 Primitive.tracepoint_attr_lineno
325 # Path of the file being run
327 Primitive.tracepoint_attr_path
330 # Return the parameters definition of the method or block that the
331 # current hook belongs to. Format is the same as for Method#parameters
333 Primitive.tracepoint_attr_parameters
336 # Return the name at the definition of the method being called
338 Primitive.tracepoint_attr_method_id
341 # Return the called name of the method being called
343 Primitive.tracepoint_attr_callee_id
346 # Return class or module of the method being called.
348 # class C; def foo; end; end
349 # trace = TracePoint.new(:call) do |tp|
350 # p tp.defined_class #=> C
355 # If method is defined by a module, then that module is returned.
357 # module M; def foo; end; end
358 # class C; include M; end;
359 # trace = TracePoint.new(:call) do |tp|
360 # p tp.defined_class #=> M
365 # <b>Note:</b> #defined_class returns singleton class.
367 # 6th block parameter of Kernel#set_trace_func passes original class
368 # of attached by singleton class.
370 # <b>This is a difference between Kernel#set_trace_func and TracePoint.</b>
372 # class C; def self.foo; end; end
373 # trace = TracePoint.new(:call) do |tp|
374 # p tp.defined_class #=> #<Class:C>
379 Primitive.tracepoint_attr_defined_class
382 # Return the generated binding object from event.
384 # Note that for +:c_call+ and +:c_return+ events, the method will return
385 # +nil+, since C methods themselves do not have bindings.
387 Primitive.tracepoint_attr_binding
390 # Return the trace object during event
392 # Same as the following, except it returns the correct object (the method
393 # receiver) for +:c_call+ and +:c_return+ events:
395 # trace.binding.eval('self')
397 Primitive.tracepoint_attr_self
400 # Return value from +:return+, +:c_return+, and +:b_return+ event
402 Primitive.tracepoint_attr_return_value
405 # Value from exception raised on the +:raise+ event, or rescued on the +:rescue+ event.
407 Primitive.tracepoint_attr_raised_exception
410 # Compiled source code (String) on *eval methods on the +:script_compiled+ event.
411 # If loaded from a file, it will return nil.
413 Primitive.tracepoint_attr_eval_script
416 # Compiled instruction sequence represented by a RubyVM::InstructionSequence instance
417 # on the +:script_compiled+ event.
419 # Note that this method is MRI specific.
420 def instruction_sequence
421 Primitive.tracepoint_attr_instruction_sequence