sstephenson/execjs

do not use therubyracer if other options are available

akostadinov opened this issue · 3 comments

Hello, at present I see that therubyracer runtime is preferred over anything else present on the system. This is not a good idea because it is not thread safe and can deadlock the whole MRI when multiple threads are calling it.

Please see rubyjs/therubyracer#432. It appears to me that gem is not well maintained so I'd suggest prefer other runtimes over it. I still can't understand how it can deadlock the whole MRI. I tried putting inside SEMAPHORE.synchronize {..} all calls to @v8_context to no avail.

For the info, I'm using awestruct which uses threads to generate static web sites. Tilt coffee script processing and AutoprefixerRails are processing files for me in the different threads. I'll try to come up with a simpler reproducer later.

-- therubyracer 0.12.3
-- execjs (2.7.0)

Here I've crafted a very simple reproducer which often hangs with therubyracer but consistently completes flawless with nodejs backend:

require 'open-uri'
require 'autoprefixer-rails'

t = "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css"
input = open(t).read

(1..10).each do
  Thread.new {
    AutoprefixerRails.process(
      input,
      from: "bootstrap.css",
      browsers: ['> 1%', 'ie 10']
    ).css
  }
end

Even simpler reproducer without any external gems:

require "execjs"

(1..10).each do
  Thread.new {
    f = ExecJS.compile %q{
    function pausecomp(millis) {
      var date = new Date();
      var curDate = null;
      do { curDate = new Date(); } while(curDate-date < millis);
    }
    }
    f.eval('pausecomp(200)')
  }
end

Basically the above easily freezes with therubyracer while Node backend completes it quickly.

Honestly it looks like RubyRacer development has ceased. I painfully ran into this issue when I started using ExecJS w/RubyRacer in production with Sidekiq. Switching to MiniRacer has mostly solved my issue (I am experiencing memory leaks which may or may not be related to my ExecJS usage)