sstephenson / execjs

Run JavaScript code from Ruby
MIT License
1.16k stars 46 forks source link

do not use therubyracer if other options are available #205

Open akostadinov opened 7 years ago

akostadinov commented 7 years ago

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 https://github.com/cowboyd/therubyracer/issues/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)

akostadinov commented 7 years ago

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
akostadinov commented 7 years ago

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.

kshahkshah commented 6 years ago

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)