Skip to content
This repository
Browse code

Wrap V8 calls with lock

  • Loading branch information...
commit a48bc7c7ad03bec4f8abde1fa76c95cccc59f818 1 parent 8c64ffb
Joshua Peek authored June 08, 2011

Showing 1 changed file with 28 additions and 4 deletions. Show diff stats Hide diff stats

  1. 32  lib/execjs/ruby_racer_runtime.rb
32  lib/execjs/ruby_racer_runtime.rb
@@ -4,8 +4,10 @@ class Context
4 4
       def initialize(source = "")
5 5
         source = source.encode('UTF-8') if source.respond_to?(:encode)
6 6
 
7  
-        @v8_context = ::V8::Context.new
8  
-        @v8_context.eval(source)
  7
+        lock do
  8
+          @v8_context = ::V8::Context.new
  9
+          @v8_context.eval(source)
  10
+        end
9 11
       end
10 12
 
11 13
       def exec(source, options = {})
@@ -20,7 +22,9 @@ def eval(source, options = {})
20 22
         source = source.encode('UTF-8') if source.respond_to?(:encode)
21 23
 
22 24
         if /\S/ =~ source
23  
-          unbox @v8_context.eval("(#{source})")
  25
+          lock do
  26
+            unbox @v8_context.eval("(#{source})")
  27
+          end
24 28
         end
25 29
       rescue ::V8::JSError => e
26 30
         if e.value["name"] == "SyntaxError"
@@ -31,7 +35,9 @@ def eval(source, options = {})
31 35
       end
32 36
 
33 37
       def call(properties, *args)
34  
-        unbox @v8_context.eval(properties).call(*args)
  38
+        lock do
  39
+          unbox @v8_context.eval(properties).call(*args)
  40
+        end
35 41
       rescue ::V8::JSError => e
36 42
         if e.value["name"] == "SyntaxError"
37 43
           raise RuntimeError, e.message
@@ -59,6 +65,24 @@ def unbox(value)
59 65
           value
60 66
         end
61 67
       end
  68
+
  69
+      private
  70
+        def lock
  71
+          result, exception = nil, nil
  72
+          V8::C::Locker() do
  73
+            begin
  74
+              result = yield
  75
+            rescue Exception => e
  76
+              exception = e
  77
+            end
  78
+          end
  79
+
  80
+          if exception
  81
+            raise exception
  82
+          else
  83
+            result
  84
+          end
  85
+        end
62 86
     end
63 87
 
64 88
     def name

2 notes on commit a48bc7c

Charles Lowell

Looks good Josh. The one caveat is that if somebody uses V8 from another thread first and does not properly lock, then ExecJS will still die even though it is locking correctly. If ExecJS happens to use V8 first, then the other thread will die if it runs without locking. That should be rare and easily fixed (by wrapping the offender it in a lock), but just wanted to make sure you know in case someone runs into it.

Sheldon Hearn

Awesome, thanks for this. Now rails-3.1 is a pleasure!

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