Make TracePoint#enable with block target current thread by default

If TracePoint#enable is passed a block, it previously started
the trace on all threads.  This changes it to trace only the
current thread by default.  To limit the scope of the change,
the current thread is only used by default if target and
target_line are both nil.  You can pass target_thread: nil
to enable tracing on all threads, to get the previous
default behavior.

Fixes [Bug #16889]
This commit is contained in:
Jeremy Evans 2021-12-27 12:52:04 -08:00
parent 6d3f447aec
commit 9c1d32a7ad
Notes: git 2022-03-30 10:15:03 +09:00
4 changed files with 70 additions and 39 deletions

View File

@ -57,6 +57,30 @@ describe 'TracePoint#enable' do
end.enable { event_name.should equal(:line) } end.enable { event_name.should equal(:line) }
end end
ruby_version_is '3.2' do
it 'enables the trace object for any thread' do
threads = []
trace = TracePoint.new(:line) do |tp|
# Runs on purpose on any Thread
threads << Thread.current
end
thread = nil
trace.enable do
line_event = true
thread = Thread.new do
event_in_other_thread = true
end
thread.join
end
threads = threads.uniq
threads.should.include?(Thread.current)
threads.should_not.include?(thread)
end
end
ruby_version_is ''...'3.2' do
it 'enables the trace object for any thread' do it 'enables the trace object for any thread' do
threads = [] threads = []
trace = TracePoint.new(:line) do |tp| trace = TracePoint.new(:line) do |tp|
@ -77,6 +101,7 @@ describe 'TracePoint#enable' do
threads.should.include?(Thread.current) threads.should.include?(Thread.current)
threads.should.include?(thread) threads.should.include?(thread)
end end
end
it 'can accept arguments within a block but it should not yield arguments' do it 'can accept arguments within a block but it should not yield arguments' do
event_name = nil event_name = nil

View File

@ -98,7 +98,7 @@ describe 'TracePoint#inspect' do
TracePoint.new(:thread_begin) { |tp| TracePoint.new(:thread_begin) { |tp|
next unless Thread.current == thread next unless Thread.current == thread
inspect ||= tp.inspect inspect ||= tp.inspect
}.enable do }.enable(target_thread: nil) do
thread = Thread.new {} thread = Thread.new {}
thread_inspection = thread.inspect thread_inspection = thread.inspect
thread.join thread.join
@ -114,7 +114,7 @@ describe 'TracePoint#inspect' do
TracePoint.new(:thread_end) { |tp| TracePoint.new(:thread_end) { |tp|
next unless Thread.current == thread next unless Thread.current == thread
inspect ||= tp.inspect inspect ||= tp.inspect
}.enable do }.enable(target_thread: nil) do
thread = Thread.new {} thread = Thread.new {}
thread_inspection = thread.inspect thread_inspection = thread.inspect
thread.join thread.join

View File

@ -727,25 +727,30 @@ CODE
def test_tracepoint_enable def test_tracepoint_enable
ary = [] ary = []
args = nil args = nil
begin
trace = TracePoint.new(:call){|tp| trace = TracePoint.new(:call){|tp|
next if !target_thread? next if !target_thread?
ary << tp.method_id ary << tp.method_id
} }
foo foo
trace.enable{|*a| trace.enable(target_thread: nil){|*a|
args = a args = a
foo foo
} }
foo foo
assert_equal([:foo], ary) assert_equal([:foo], ary)
assert_equal([], args) assert_equal([], args)
ensure
trace&.disable
end
trace = TracePoint.new{} trace = TracePoint.new{}
begin begin
assert_equal(false, trace.enable) assert_equal(false, trace.enable)
assert_equal(true, trace.enable) assert_equal(true, trace.enable)
trace.enable{} trace.enable(target_thread: nil){}
assert_equal(true, trace.enable) trace.disable
assert_equal(false, trace.enable)
ensure ensure
trace.disable trace.disable
end end
@ -977,7 +982,7 @@ CODE
tp.defined_class, #=> nil, tp.defined_class, #=> nil,
tp.self.class # tp.self return creating/ending thread tp.self.class # tp.self return creating/ending thread
] ]
}.enable{ }.enable(target_thread: nil){
created_thread = Thread.new{thread_self = self} created_thread = Thread.new{thread_self = self}
created_thread.join created_thread.join
} }
@ -2239,7 +2244,7 @@ CODE
# global TP and targeted TP # global TP and targeted TP
ex = assert_raise(ArgumentError) do ex = assert_raise(ArgumentError) do
tp = TracePoint.new(:line){} tp = TracePoint.new(:line){}
tp.enable{ tp.enable(target_thread: nil){
tp.enable(target: code2){} tp.enable(target: code2){}
} }
end end
@ -2285,7 +2290,7 @@ CODE
events << :___ events << :___
end end
end end
assert_equal [:tp1, :tp1, :tp1, :tp1, :tp2, :tp1, :___], events assert_equal [:tp1, :tp1, :tp1, :tp1, :tp1, :tp2, :tp1, :___], events
# success with two tracepoints (targeting/global) # success with two tracepoints (targeting/global)
events = [] events = []

View File

@ -153,7 +153,7 @@ class TracePoint
# call-seq: # 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) -> true or false
# trace.enable(target: nil, target_line: nil, target_thread: nil) { block } -> obj # trace.enable(target: nil, target_line: nil, target_thread: Thread.current) { block } -> obj
# #
# Activates the trace. # Activates the trace.
# #
@ -168,14 +168,15 @@ class TracePoint
# # trace is still enabled # # trace is still enabled
# #
# If a block is given, the trace will only be enabled within the scope of the # If a block is given, the trace will only be enabled within the scope of the
# block. # block. If target and target_line are both nil, then target_thread will default
# to the current thread if a block is given.
# #
# trace.enabled? # trace.enabled?
# #=> false # #=> false
# #
# trace.enable do # trace.enable do
# trace.enabled? # trace.enabled?
# # only enabled for this block # # only enabled for this block and thread
# end # end
# #
# trace.enabled? # trace.enabled?
@ -208,7 +209,7 @@ class TracePoint
# trace.enable { p tp.lineno } # trace.enable { p tp.lineno }
# #=> RuntimeError: access from outside # #=> RuntimeError: access from outside
# #
def enable(target: nil, target_line: nil, target_thread: nil) def enable(target: nil, target_line: nil, target_thread: (Thread.current if target.nil? && target_line.nil? && defined?(yield)))
Primitive.tracepoint_enable_m(target, target_line, target_thread) Primitive.tracepoint_enable_m(target, target_line, target_thread)
end end