The code in lib/opal/rspec/rake_task.rb has a race condition in the following area:
server = fork do
app = Opal::Server.new { |s|
s.main = 'opal/rspec/sprockets_runner'
s.append_path 'spec'
s.debug = false
block.call s if block
}
Rack::Server.start(:app => app, :Port => PORT, :AccessLog => [],
:Logger => WEBrick::Log.new("/dev/null"))
end
system "phantomjs #{RUNNER} \"#{URL}\""
success = $?.success?
Process.kill(:SIGINT, server)
Process.wait
phantomjs can attempt to run before the Rack::Server object is ready to serve, and as a result phantomjs fails, Rack gets a SIGINT in an unfortunate place, and no tests are run. I get the following traceback in this case:
vauxhall no % rake --trace opal:rspec
** Invoke opal:rspec (first_time)
** Execute opal:rspec
Cannot load: http://localhost:9999/
/usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `const_get': can't be called from trap context (ThreadError)
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `block in get'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `each'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `inject'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `get'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:38:in `block in pick'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:36:in `each'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:36:in `pick'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:57:in `default'
from /usr/lib/ruby/vendor_ruby/rack/server.rb:268:in `server'
from /usr/lib/ruby/vendor_ruby/rack/server.rb:257:in `block in start'
from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `call'
from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `block (2 levels) in contains_requirable_file?'
from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `each'
from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `any?'
from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:62:in `block in contains_requirable_file?'
from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:60:in `each'
from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:60:in `any?'
from /usr/lib/ruby/2.1.0/rubygems/basic_specification.rb:60:in `contains_requirable_file?'
from /usr/lib/ruby/2.1.0/rubygems/specification.rb:915:in `block in find_by_path'
from /usr/lib/ruby/2.1.0/rubygems/specification.rb:883:in `block in each'
from /usr/lib/ruby/2.1.0/rubygems/specification.rb:882:in `each'
from /usr/lib/ruby/2.1.0/rubygems/specification.rb:882:in `each'
from /usr/lib/ruby/2.1.0/rubygems/specification.rb:914:in `find'
from /usr/lib/ruby/2.1.0/rubygems/specification.rb:914:in `find_by_path'
from /usr/lib/ruby/2.1.0/rubygems.rb:188:in `try_activate'
from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:132:in `rescue in require'
from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:144:in `require'
from /usr/lib/ruby/vendor_ruby/rack/handler/thin.rb:1:in `<top (required)>'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `const_get'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `block in get'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `each'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `inject'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:20:in `get'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:38:in `block in pick'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:36:in `each'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:36:in `pick'
from /usr/lib/ruby/vendor_ruby/rack/handler.rb:57:in `default'
from /usr/lib/ruby/vendor_ruby/rack/server.rb:268:in `server'
from /usr/lib/ruby/vendor_ruby/rack/server.rb:264:in `start'
from /usr/lib/ruby/vendor_ruby/rack/server.rb:141:in `start'
from /var/lib/gems/2.1.0/gems/opal-rspec-0.4.0/lib/opal/rspec/rake_task.rb:27:in `block (2 levels) in initialize'
from /var/lib/gems/2.1.0/gems/opal-rspec-0.4.0/lib/opal/rspec/rake_task.rb:18:in `fork'
from /var/lib/gems/2.1.0/gems/opal-rspec-0.4.0/lib/opal/rspec/rake_task.rb:18:in `block in initialize'
from /usr/lib/ruby/vendor_ruby/rake/task.rb:240:in `call'
from /usr/lib/ruby/vendor_ruby/rake/task.rb:240:in `block in execute'
from /usr/lib/ruby/vendor_ruby/rake/task.rb:235:in `each'
from /usr/lib/ruby/vendor_ruby/rake/task.rb:235:in `execute'
from /usr/lib/ruby/vendor_ruby/rake/task.rb:179:in `block in invoke_with_call_chain'
from /usr/lib/ruby/2.1.0/monitor.rb:211:in `mon_synchronize'
from /usr/lib/ruby/vendor_ruby/rake/task.rb:172:in `invoke_with_call_chain'
from /usr/lib/ruby/vendor_ruby/rake/task.rb:165:in `invoke'
from /usr/lib/ruby/vendor_ruby/rake/application.rb:150:in `invoke_task'
from /usr/lib/ruby/vendor_ruby/rake/application.rb:106:in `block (2 levels) in top_level'
from /usr/lib/ruby/vendor_ruby/rake/application.rb:106:in `each'
from /usr/lib/ruby/vendor_ruby/rake/application.rb:106:in `block in top_level'
from /usr/lib/ruby/vendor_ruby/rake/application.rb:115:in `run_with_threads'
from /usr/lib/ruby/vendor_ruby/rake/application.rb:100:in `top_level'
from /usr/lib/ruby/vendor_ruby/rake/application.rb:78:in `block in run'
from /usr/lib/ruby/vendor_ruby/rake/application.rb:176:in `standard_exception_handling'
from /usr/lib/ruby/vendor_ruby/rake/application.rb:75:in `run'
from /usr/bin/rake:27:in `<main>'
Inserting a sleep 2 after the fork block makes it work correctly.
The code in
lib/opal/rspec/rake_task.rb
has a race condition in the following area:phantomjs can attempt to run before the Rack::Server object is ready to serve, and as a result phantomjs fails, Rack gets a SIGINT in an unfortunate place, and no tests are run. I get the following traceback in this case:
Inserting a sleep 2 after the fork block makes it work correctly.