datamapper/do — pull request #43 by bmatcuk (2012-10-09 01:37:15+00:00)
Title: Prevent "Pooling" from being included more than once.

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.