[ruby-core:105031] [Ruby master Bug#16889] TracePoint.enable { ... } also activates the TracePoint for other threads, even outside the block
From:
"Eregon (Benoit Daloze)" <noreply@...>
Date:
2021-08-20 21:48:59 UTC
List:
ruby-core #105031
Issue #16889 has been updated by Eregon (Benoit Daloze).
mame (Yusuke Endoh) wrote in #note-13:
> Agreed. I think thread-local behavior is more reasonable. So, the current `target: :block` is not what you want, right?
Indeed. I'm not against it but I don't think it's necessary or so helpful.
> Though I like thread-local behavior, I have some concerns:
>
> * `tp.enable { Thread.new { foo }.join }` will not trace `foo` because it is run in another thread, but I'm unsure if this is expected.
I think it is expected. `foo` is not on the call stack of that `tp.enable` (it does have that `TracePoint#enable` as a caller).
With that logic I would also prefer if `tp.enable { Fiber.new { foo }.resume }` does not trace `foo`, but it is less important, as that could only happen if the `enable` blocks switches Fibers (probably rare).
Currently, `Thread.new { sleep 1; foo }; tp.enable { bar }` will trace `bar` (expected) but also `foo` (I find that unexpected/unintuitive).
> * `tp.enable` called with no block should trace events in all threads, right? It is a bit inconsistent, but perhaps changing this to thread-local will break [Zeitwerk](https://github.com/fxn/zeitwerk/blob/243b43acde6f88893c2d02b191227c2917745a4f/test/lib/zeitwerk/test_ruby_compatibility.rb#L69-L70).
Yes, `tp.enable` (no block) should trace events everywhere, I think that's intuitive, it doesn't provide any "target" or "context" so it's global.
----------------------------------------
Bug #16889: TracePoint.enable { ... } also activates the TracePoint for other threads, even outside the block
https://bugs.ruby-lang.org/issues/16889#change-93440
* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN
----------------------------------------
```ruby
threads = []
inspects = []
trace = TracePoint.new(:line) do |tp|
threads << Thread.current
inspects << tp.inspect
end
done = false
thread = Thread.new do
Thread.pass until done
end
trace.enable do
line_event = true
done = true
sleep 1
end
thread.join
# Expected only within enable block (lines 14-16)
puts inspects
# Expected just 1
p threads.uniq
```
Results in:
```
$ ruby tpbug.rb
ruby tpbug.rb
#<TracePoint:line@tpbug.rb:14>
#<TracePoint:line@tpbug.rb:15>
#<TracePoint:line@tpbug.rb:16>
#<TracePoint:line@tpbug.rb:10>
[#<Thread:0x00005571134e3340 run>, #<Thread:0x00005571138ac828@tpbug.rb:9 dead>]
```
But I expected:
```
#<TracePoint:line@tpbug.rb:14>
#<TracePoint:line@tpbug.rb:15>
#<TracePoint:line@tpbug.rb:16>
[#<Thread:0x00005571134e3340 run>]
```
Because the RDoc says:
```
If a block is given, the trace will only be enabled within the scope of
the block.
```
For background I'm trying to improve the TracePoint specs in ruby/spec, but they are proving quite unreliable due to this.
@ko1 Thoughts?
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>