eagerly initialize the attributes module to avoid check-then-set race conditions

This commit is contained in:
Aaron Patterson 2013-07-02 14:34:03 -07:00
parent 77f40cf9aa
commit 09b31f08d4
3 changed files with 17 additions and 9 deletions

View File

@ -1,4 +1,5 @@
require 'thread_safe'
require 'mutex_m'
module ActiveModel
# Raised when an attribute is not defined.
@ -333,7 +334,9 @@ module ActiveModel
end
def generated_attribute_methods #:nodoc:
@generated_attribute_methods ||= Module.new.tap { |mod| include mod }
@generated_attribute_methods ||= Module.new {
extend Mutex_m
}.tap { |mod| include mod }
end
protected

View File

@ -1,4 +1,5 @@
require 'active_support/core_ext/enumerable'
require 'mutex_m'
module ActiveRecord
# = Active Record Attribute Methods
@ -18,12 +19,22 @@ module ActiveRecord
end
module ClassMethods
def inherited(child_class) #:nodoc:
child_class.initialize_generated_modules
super
end
def initialize_generated_modules # :nodoc:
@generated_attribute_methods = Module.new { extend Mutex_m }
include @generated_attribute_methods
end
# Generates all the attribute related methods for columns in the database
# accessors, mutators and query methods.
def define_attribute_methods # :nodoc:
# Use a mutex; we don't want two thread simultaneously trying to define
# attribute methods.
@attribute_methods_mutex.synchronize do
generated_attribute_methods.synchronize do
return if attribute_methods_generated?
superclass.define_attribute_methods unless self == base_class
super(column_names)

View File

@ -88,14 +88,8 @@ module ActiveRecord
end
module ClassMethods
def inherited(child_class) #:nodoc:
child_class.initialize_generated_modules
super
end
def initialize_generated_modules
@attribute_methods_mutex = Mutex.new
super
# force attribute methods to be higher in inheritance hierarchy than other generated methods
generated_attribute_methods.const_set(:AttrNames, Module.new {
def self.const_missing(name)