Skip to content
This repository
Browse code

Prevent concurrent compilation of templates - closes #6400

  • Loading branch information...
commit 565c1b0a0772ac6cf91c77e9285806f7b028614c 1 parent 5284e65
pinetops authored May 20, 2012

Showing 1 changed file with 22 additions and 10 deletions. Show diff stats Hide diff stats

  1. 32  actionpack/lib/action_view/template.rb
32  actionpack/lib/action_view/template.rb
@@ -2,6 +2,7 @@
2 2
 require 'active_support/core_ext/object/blank'
3 3
 require 'active_support/core_ext/object/try'
4 4
 require 'active_support/core_ext/kernel/singleton_class'
  5
+require 'thread'
5 6
 
6 7
 module ActionView
7 8
   # = Action View Template
@@ -123,6 +124,7 @@ def initialize(source, identifier, handler, details)
123 124
       @virtual_path      = details[:virtual_path]
124 125
       @updated_at        = details[:updated_at] || Time.now
125 126
       @formats = Array.wrap(format).map { |f| f.is_a?(Mime::Type) ? f.ref : f }
  127
+      @compile_mutex     = Mutex.new
126 128
     end
127 129
 
128 130
     # Returns if the underlying handler supports streaming. If so,
@@ -224,18 +226,28 @@ def encode!
224 226
       def compile!(view) #:nodoc:
225 227
         return if @compiled
226 228
 
227  
-        if view.is_a?(ActionView::CompiledTemplates)
228  
-          mod = ActionView::CompiledTemplates
229  
-        else
230  
-          mod = view.singleton_class
231  
-        end
  229
+        # Templates can be used concurrently in threaded environments
  230
+        # so compilation and any instance variable modification must
  231
+        # be synchronized
  232
+        @compile_mutex.synchronize do
  233
+          # Any thread holding this lock will be compiling the template needed
  234
+          # by the threads waiting. So re-check the @compiled flag to avoid
  235
+          # re-compilation
  236
+          return if @compiled
  237
+
  238
+          if view.is_a?(ActionView::CompiledTemplates)
  239
+            mod = ActionView::CompiledTemplates
  240
+          else
  241
+            mod = view.singleton_class
  242
+          end
232 243
 
233  
-        compile(view, mod)
  244
+          compile(view, mod)
234 245
 
235  
-        # Just discard the source if we have a virtual path. This
236  
-        # means we can get the template back.
237  
-        @source = nil if @virtual_path
238  
-        @compiled = true
  246
+          # Just discard the source if we have a virtual path. This
  247
+          # means we can get the template back.
  248
+          @source = nil if @virtual_path
  249
+          @compiled = true
  250
+        end
239 251
       end
240 252
 
241 253
       # Among other things, this method is responsible for properly setting

0 notes on commit 565c1b0

Please sign in to comment.
Something went wrong with that request. Please try again.