From: "hurricup (Alexandr Evstigneev)" Date: 2022-04-27T06:36:45+00:00 Subject: [ruby-core:108410] [Ruby master Bug#18730] Double `return` event handling with different tracepoints Issue #18730 has been updated by hurricup (Alexandr Evstigneev). jeremyevans0 (Jeremy Evans) wrote in #note-2: > You are adding and enabling a separate return event tracepoint (`tp_multi2`) on the same method before the method returns, while it is still in the process of handling the first return event tracepoint (`tp_multi1`). I don't think it is unexpected that this tracepoint (`tp_multi2`) would also be called. Note that if you add a `tp_multi2.disable` call directly after the `tp_multi2.enable` call, you don't get the second return event printed. My points are: 1. This is inconsistent with pre 2.6 behavior, when tp set inside the tp handler was not triggered by the same event. 2. Other TPs should not affect this behavior, it should be consistent. I'm not saying that it is definitely wrong to trigger such TP, but it feels wrong. Because VM already started processing `:return` event and invoking hooks. And not sure that it should invoke handlers set after processing started. But this is my personal feeling, nothing objective. Still, may be such behavior is an opportunity to implement some tricky things, hard to say, but need to be consistent for sure, one way or another. ---------------------------------------- Bug #18730: Double `return` event handling with different tracepoints https://bugs.ruby-lang.org/issues/18730#change-97445 * Author: hurricup (Alexandr Evstigneev) * Status: Open * Priority: Normal * Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN ---------------------------------------- I'm not sure if this is a bug or intentional behavior, but feels a bit unexpected. Ruby 3.0.x, 3.1.x affected. Here is the script demonstrating the issue: ``` def bar 42 #bp here end tp_line = TracePoint.new(:line) do |tp0| puts "Got line event from #{tp0.path}:#{tp0.lineno}" tp_multi1 = TracePoint.new(:return, :b_return, :line) do |tp| if tp.lineno == 3 puts "Got first return `#{tp.event}` from #{tp.path}:#{tp.lineno}" tp.disable # tp0.disable # uncommenting this line changes things to the more expected tp_multi2 = TracePoint.new(:return, :b_return, :line) do |tps| puts "Got second return `#{tps.event}` from #{tps.path}:#{tps.lineno}" end tp_multi2.enable(target: RubyVM::InstructionSequence.of(method :bar)) end end tp_multi1.enable end tp_line.enable(target: RubyVM::InstructionSequence.of(method :bar)) bar ``` 1. We set a line TP to the `bar` method `iseq` (consider it a line breakpoint) 2. When line event is triggered we setting another untargeted tracepoint for the same method, to catch `line`, `return` and `b_return` events (consider it attempt to step into something) 3. When return event of the `bar` method is triggered, we disabling second tracepoint and setting another one, targeted to the same method and multiple events. Output i get: ``` Got line event from /home/hurricup/test.rb:2 Got first return `return` from /home/hurricup/test.rb:3 Got second return `return` from /home/hurricup/test.rb:3 ``` The questions are: 1. why return triggered on the second tracepoint, when we already handeled it? 2. why disabling line tracepoint changes behavior? -- https://bugs.ruby-lang.org/ Unsubscribe: