This project is archived and is in readonly mode.

#5639 ✓stale
lcars

define_attribute_methods race leads to method missing exception while creating objects conccurently

Reported by lcars | September 16th, 2010 @ 11:10 AM

Hi, we are experiencing random 'undefined method' errors while creating objects in an heavily threaded environment, here's an example:

caught exception in vendor/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/attribute_method
s.rb:255:in method_missing'

undefined method uuid=' for #<OurObject:0xdef731> ... etc etc

with random I mean very rarely and apparently only once after application startup. In OurObject 'uuid' is the primary key. The code which leads to the exception is the following:

o = new(params)
o.uuid = params['uuid']

We think this might be a race in how method_missing override (in attribute_methods.rb) checks if all attribute methods have been defined before invoking super on ruby's own method_missing.

If we check the define_attribute_methods we see the following:

def define_attribute_methods

return if generated_methods?

...

end

This means that define_attribute_methods returns if any number (even just one out of hunders ) of methods have been added to the @generated_methods instance set for the object columns.

Considering this along with the fact that these are all class methods without mutex protection, is it possible in an heavily threaded environment for two objects of the same class, in separate threads, to invoke define_attribute_methods at the same time making one of the two bailing out prematurely because generated_methods? was satisfied that at least one attribute method was set (by the other thread) ?

This would lead to method_missing skipping this conditional:

if !self.class.generated_methods?

self.class.define_attribute_methods
if self.class.generated_methods.include?(method_name)
  return self.send(method_id, *args, &block)
end

end

...and eventually hitting the super which would cause the exception.

Unfortunately I don't have time to create a test for this.

Thanks

Comments and changes to this ticket

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:31 PM

    • State changed from “new” to “open”

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:31 PM

    • State changed from “open” to “stale”

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

People watching this ticket

Pages