Prevent concurrent compilation of templates - closes #6400

This commit is contained in:
Tom Clarke
2012-05-20 12:41:58 -04:00
parent 5284e650be
commit 565c1b0a07

View File

@@ -2,6 +2,7 @@ require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/object/try'
require 'active_support/core_ext/kernel/singleton_class'
require 'thread'
module ActionView
# = Action View Template
@@ -123,6 +124,7 @@ module ActionView
@virtual_path = details[:virtual_path]
@updated_at = details[:updated_at] || Time.now
@formats = Array.wrap(format).map { |f| f.is_a?(Mime::Type) ? f.ref : f }
@compile_mutex = Mutex.new
end
# Returns if the underlying handler supports streaming. If so,
@@ -224,18 +226,28 @@ module ActionView
def compile!(view) #:nodoc:
return if @compiled
if view.is_a?(ActionView::CompiledTemplates)
mod = ActionView::CompiledTemplates
else
mod = view.singleton_class
# Templates can be used concurrently in threaded environments
# so compilation and any instance variable modification must
# be synchronized
@compile_mutex.synchronize do
# Any thread holding this lock will be compiling the template needed
# by the threads waiting. So re-check the @compiled flag to avoid
# re-compilation
return if @compiled
if view.is_a?(ActionView::CompiledTemplates)
mod = ActionView::CompiledTemplates
else
mod = view.singleton_class
end
compile(view, mod)
# Just discard the source if we have a virtual path. This
# means we can get the template back.
@source = nil if @virtual_path
@compiled = true
end
compile(view, mod)
# Just discard the source if we have a virtual path. This
# means we can get the template back.
@source = nil if @virtual_path
@compiled = true
end
# Among other things, this method is responsible for properly setting