Project

General

Profile

Actions

Bug #21338

closed

TracePoint Not Triggered for Kernel#block_given?

Added by cfis (Charlie Savage) 16 days ago. Updated 11 days ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [x86_64-linux]
[ruby-core:122091]

Description

When updating ruby-prof for Ruby 3.4, various tests now fail because a method enter/leave tracepoint is not triggered for Kernel#block_given? For example:

https://github.com/ruby-prof/ruby-prof/blob/master/test/line_number_test.rb#L184

In 3.3 a tracepoint was triggered but not in earlier Ruby versions.

Updated by alanwu (Alan Wu) 16 days ago

  • Status changed from Open to Rejected

It's a C method in 3.4, so you can listen for :c_call:

ruby -ve 'TracePoint.new(:c_call) { p _1 }.enable { block_given? }'

Wether something is a C or Ruby method is not something we guarantee to be stable, though, so it's not a bug now that a different event fires.

Updated by cfis (Charlie Savage) 15 days ago · Edited

ruby-prof does listen for C calls. See:

https://github.com/ruby-prof/ruby-prof/blob/master/ext/ruby_prof/rp_profile.c#L337

void prof_install_hook(VALUE self)
{
    prof_profile_t* profile = prof_get_profile(self);

    VALUE event_tracepoint = rb_tracepoint_new(Qnil,
                                               RUBY_EVENT_CALL | RUBY_EVENT_RETURN |
                                               RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN |
                                               RUBY_EVENT_LINE,
                                               prof_event_hook, profile);

Once again, this is change in behavior between 3.3 and 3.4. Was it intentional?

Updated by alanwu (Alan Wu) 14 days ago · Edited

Yes, we intentionally moved the implementation for block_given? to C. Again, a method can move between C and Ruby between versions.

I just tested rb_tracepoint_new() with RUBY_EVENT_C_CALL and block_given?, and an event definitely fires. This feels like you have a bug in your code. Are there any other behavior change you're seeing?

Updated by k0kubun (Takashi Kokubun) 14 days ago · Edited

I see that you're calling Numeric#times in your profiled test code. We used to use a block_given? C call inside it to check if a block is given. @nobu (Nobuyoshi Nakada) changed it to defined?(yield) at 3dccb716daaee74d2ae00a5766fe1779fe220a81 to protect it from possible method redefinitions of block_given?. So block_given? is no longer called in Ruby 3.4. I think that's what's happening in your test code.

It's effectively testing the implementation details of CRuby core methods like Numeric#times. And it can change between different Ruby minor versions. To make the test code less fragile, I recommend you to define every method you call in the profiled code yourself.

Updated by cfis (Charlie Savage) 11 days ago · Edited

Hi @k0kubun (Takashi Kokubun) - ok great - that sounds like an intentional change in Ruby 3.4 then.

I don't understand your recommendation though "to define every method you call in the profiled code yourself". The ruby-prof test code has remained fairly consistent over the years. What has changed is that each new version of Ruby returns slightly different results. For example, 3.3 started reporting block_given? was called and then 3.4 removed it. Anyway, that's fine, I will update the test code. It already has a lot of version checks like this:

if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.3')
....
else
...
end

See https://github.com/ruby-prof/ruby-prof/blob/master/test/measure_wall_time_test.rb#L160

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0