The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Functions accepting blocks in Ruby's C API make for tricky bugs

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Eigen Class

Posts: 358
Nickname: eigenclass
Registered: Oct, 2005

Eigenclass is a hardcore Ruby blog.
Functions accepting blocks in Ruby's C API make for tricky bugs Posted: Aug 18, 2006 7:18 PM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Eigen Class.
Original Post: Functions accepting blocks in Ruby's C API make for tricky bugs
Feed Title: Eigenclass
Feed URL: http://feeds.feedburner.com/eigenclass
Feed Description: Ruby stuff --- trying to stay away from triviality.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Eigen Class
Latest Posts From Eigenclass

Advertisement

I ran into a tricky bug today. I was working on an extension that uses an event_hook and needed quite some time to figure this out:

require 'binding_n'
def e
  l = eval("local_variables", binding)
  puts "The array: #{l.inspect}"
  l.map do |str|
    puts "PROCESSING #{str.inspect}"
    [str, eval(str, binding)]
  end
end

Kernel.install_binding_n_hook
e
Kernel.remove_binding_n_hook

The block was evaluated twice, even though the array had but one element:

The array: ["l"]
PROCESSING "l"
PROCESSING nil
t.rb:7:in `eval': can't convert nil into String (TypeError)
        from t.rb:7:in `e'
        from t.rb:5:in `e'
        from t.rb:12

I finally tracked it down to this function, which was being executed on RUBY_EVENT_(C)_RETURN events:

static inline code_site_t *
callsite_stack_pop(callsite_stack_t *stack)
{
    if (stack->ptr == stack->start) {
        return stack->ptr;
    }
    rb_hash_delete(additional_gc_roots, (stack->ptr-1)->binding); 
    return --stack->ptr;
}

Can you spot the culprit?

Methods taking a block and implemented in C, at risk

If the key is not found, rb_hash_delete will yield it to the current block, if present. But which block is that? It's harder to see in C...

That would be the block passed to the current method, i.e. the one you rb_define_method()'d. Or, in this particular case, the method we were returning from (remember this was being executed in an event_hook).

This means that you have to be careful whenever you use a function from Ruby's C API that admits a block and you do not want one passed. The fix looks like this:


Read more...

Read: Functions accepting blocks in Ruby's C API make for tricky bugs

Topic: Setting $stdout per-thread Previous Topic   Next Topic Topic: class Goal; has_many :sub_goals; end

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use