datamapper / do

DataObjects
147 stars 74 forks source link

Prevent "Pooling" from being included more than once. #43

Closed bmatcuk closed 11 years ago

bmatcuk commented 11 years ago

In our JRuby environment, we were seeing an odd error that only occurred sometimes, right after tomcat was spun up: "Mutex relocking by same thread". The stack trace looked like this:

gems/gems/data_objects-0.10.9/lib/data_objects/pooling.rb:172:in `new'
gems/gems/data_objects-0.10.9/lib/data_objects/pooling.rb:119:in `new'
gems/gems/data_objects-0.10.9/lib/data_objects/pooling.rb:177:in `new'
gems/gems/data_objects-0.10.9/lib/data_objects/pooling.rb:172:in `new'
gems/gems/data_objects-0.10.9/lib/data_objects/pooling.rb:119:in `new'
gems/gems/data_objects-0.10.9/lib/data_objects/connection.rb:68:in `new'

The Pooling module was being included on DataObjects::Postgres::Connection more than once. This resulted in the "__new" alias pointing to the "new" method defined in Pooling's class_eval (inside def self.included()) instead of pointing to Class.new as was intended. When __new was called on line 177, it was really calling "new" defined on line 119, which would call back to the lock.synchronize on line 172 and it would blow up.

My change simply prevents that from happening: first, the existing module mutex in Pooling is used to ensure that Pooling.included() is thread safe. Second, the "target" is checked to see if Pooling has already been included (by checking if "__pools" exists on the target).

I'm not sure if it is the best solution to this problem, but it works.

dbussink commented 11 years ago

Sounds like a good fix for now. Pooling might need some revision in general, but that's of a later concern atm.