akephalos icon indicating copy to clipboard operation
akephalos copied to clipboard

Spork compatible

Open marcandre opened this issue 13 years ago • 18 comments

Hi!

Is akephalos meant to be compatible with Spork?

I just added two tests requiring javascript.

If I put the "require 'akephalos'; Capybara.javascript_driver = :akephalos" at the end of the Spork.prefork, then spork segfaults when the test is run (from autotest): /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1480: [BUG] Segmentation fault

If I put it in the Spork.each_run, it crashes sometimes, or else I get strange error messages: "0x84cbae60 is recycled object" and "undefined method `call' for "sig_int_received":String" (full backtrace at the end).

When ran without Spork, the tests pass/fail as they should.

Using: Ruby 1.8.7 p174, and latest autotest, capybara, rspec, OS X, rails.

Any idea?

Thanks

 1) Visit Creation from a Store schedule widget interracts correctly
 Failure/Error: date = find("#visit_scheduled_at")
 0x84cc4a8c is recycled object
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:375:in `_id2ref'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:375:in `to_obj'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1410:in `to_obj'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1718:in `to_obj'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:613:in `recv_request'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:913:in `recv_request'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1538:in `init_with_client'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1550:in `setup_message'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1502:in `perform'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1597:in `main_loop'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1593:in `loop'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1593:in `main_loop'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1589:in `start'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1589:in `main_loop'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1438:in `run'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1435:in `start'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1435:in `run'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1355:in `initialize'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1635:in `new'
 # (druby://127.0.0.1:8989) /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1635:in `start_service'
 # (druby://127.0.0.1:8989) /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/server.rb:29:in `listen'
 # (druby://127.0.0.1:8989) /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/server.rb:20:in `run'
 # (druby://127.0.0.1:8989) /Library/Ruby/Gems/1.8/gems/spork-0.8.4/bin/../lib/spork/runner.rb:75:in `run'
 # (druby://127.0.0.1:8989) /Library/Ruby/Gems/1.8/gems/spork-0.8.4/bin/../lib/spork/runner.rb:9:in `run'
 # (druby://127.0.0.1:8989) /Library/Ruby/Gems/1.8/gems/spork-0.8.4/bin/spork:10
 # (druby://127.0.0.1:8989) /Library/Ruby/Gems/1.8/bin/spork:19:in `load'
 # (druby://127.0.0.1:8989) /Library/Ruby/Gems/1.8/bin/spork:19
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/invokemethod.rb:10:in `block_yield'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/invokemethod.rb:17:in `perform_with_block'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/invokemethod.rb:14:in `each'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/invokemethod.rb:14:in `perform_with_block'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1551:in `perform'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1627:in `main_loop'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1623:in `loop'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1623:in `main_loop'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1619:in `start'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1619:in `main_loop'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1468:in `run'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1465:in `start'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1465:in `run'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1385:in `initialize'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1665:in `new'
 # (druby://127.0.0.1:52909) file:/Library/Ruby/Gems/1.8/gems/jruby-jars-1.5.6/lib/jruby-stdlib-1.5.6.jar!/META-INF/jruby.home/lib/ruby/1.8/drb/drb.rb:1665:in `start_service'
 # (druby://127.0.0.1:52909) /Library/Ruby/Gems/1.8/gems/akephalos-0.2.5/lib/akephalos/server.rb:58:in `start!'
 # (druby://127.0.0.1:52909) -e:1
 # /Library/Ruby/Gems/1.8/gems/akephalos-0.2.5/lib/akephalos/capybara.rb:269:in `find'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/node/finders.rb:160:in `find_in_base'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/node/finders.rb:147:in `first'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/node/finders.rb:146:in `each'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/node/finders.rb:146:in `first'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/node/finders.rb:28:in `find'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/node/finders.rb:168:in `wait_conditionally_until'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/node/finders.rb:28:in `find'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/session.rb:271:in `send'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/session.rb:271:in `method_missing'
 # /Library/Ruby/Gems/1.8/bundler/gems/capybara-47dbcdfdf0ae/lib/capybara/dsl.rb:134:in `find'
 # ./spec/acceptance/create_visit_spec.rb:11
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:47:in `instance_eval'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:47:in `run'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:86:in `call'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:86:in `with_around_hooks'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:44:in `run'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:80:in `call'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:80:in `with_pending_capture'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:79:in `catch'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:79:in `with_pending_capture'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example.rb:43:in `run'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example_group.rb:260:in `run_examples'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example_group.rb:256:in `map'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example_group.rb:256:in `run_examples'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example_group.rb:230:in `run'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example_group.rb:231:in `run'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example_group.rb:231:in `map'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/example_group.rb:231:in `run'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/command_line.rb:26:in `run'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/command_line.rb:26:in `map'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/command_line.rb:26:in `run'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/reporter.rb:11:in `report'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/core/command_line.rb:23:in `run'
 # /Library/Ruby/Gems/1.8/gems/rspec-core-2.0.1/lib/rspec/monkey/spork/test_framework/rspec.rb:4:in `run_tests'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/run_strategy/forking.rb:13:in `run'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/run_strategy/magazine/../../../spork/forker.rb:21:in `initialize'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/run_strategy/magazine/../../../spork/forker.rb:18:in `fork'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/run_strategy/magazine/../../../spork/forker.rb:18:in `initialize'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/run_strategy/forking.rb:9:in `new'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/run_strategy/forking.rb:9:in `run'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/server.rb:47:in `run'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1563:in `__send__'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1563:in `perform_without_block'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1523:in `perform'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1597:in `main_loop'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1593:in `loop'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1593:in `main_loop'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1589:in `start'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1589:in `main_loop'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1438:in `run'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1435:in `start'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1435:in `run'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1355:in `initialize'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1635:in `new'
 # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1635:in `start_service'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/server.rb:29:in `listen'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/lib/spork/server.rb:20:in `run'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/bin/../lib/spork/runner.rb:75:in `run'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/bin/../lib/spork/runner.rb:9:in `run'
 # /Library/Ruby/Gems/1.8/gems/spork-0.8.4/bin/spork:10
 # /Library/Ruby/Gems/1.8/bin/spork:19:in `load'
 # /Library/Ruby/Gems/1.8/bin/spork:19

marcandre avatar Mar 08 '11 23:03 marcandre

I also see this problem on Ruby 1.9.2 p0.

matthewtodd avatar Mar 09 '11 10:03 matthewtodd

And ruby 1.9.2p180, and Spork 0.9

Nerian avatar Mar 10 '11 18:03 Nerian

It seems to be a problem with garbage collection. I tried setting the minimum memory for the VM to be 512 MB in order to minimise Garbage collection (the default is 64 mb). But the results are the same, all test fails with the recycled object error.

Upgrading to the last jruby-jar didn't solve the problem either (but hey, all akephalos' tests pass).

I tried disabling GC, but being JRuby the statement GC.disable doesn't do anything.

Mmm....

Nerian avatar Mar 10 '11 20:03 Nerian

doesn't help much, but I can confirm the problem for ruby 192p180, spork 084 --Frank

fwoeck avatar Apr 05 '11 12:04 fwoeck

I can also confirm the problem with akephalos 0.2.5 and spork 0.9.0.rc4

aaronjensen avatar Apr 05 '11 17:04 aaronjensen

I too can see this issue, Ruby 1.9.2, Spork 0.9.0.rc4, Akephalos 0.2.5

mattheworiordan avatar Apr 09 '11 11:04 mattheworiordan

Let wait for @bernerdschaefer insight :)

Nerian avatar Apr 10 '11 23:04 Nerian

Also have this issue on Ruby 1.9.2 spork 0.9.0.rc Akephalos 0.2.5

damrbaby avatar May 05 '11 18:05 damrbaby

Any ideas on this? I would be happy to delve in if someone has a place to start. Seems like a GC issue but I defer to the experts.

lightsofapollo avatar May 23 '11 06:05 lightsofapollo

It is a problem with the GC. Akephalos uses HTMLUnit, which runs on JRuby. I suspect that some object is being garbage collected in the JRuby part. But I haven't figure it out where and I am no an expert at JRuby either :)

I have tried increasing the available memory that the java virtual machine can use, but the problem persists.

Nerian avatar May 23 '11 13:05 Nerian

I will take a look into this over the next week during my free time.

lightsofapollo avatar May 24 '11 02:05 lightsofapollo

I'm totally new to akephalos and never used spork but this type of error can occur with DRb if the DRb server creates an object, doesn't keep a reference to it, and a client doesn't immediately request it. The server will GC the object and the client will get another object after the GC. The server side might need to keep a class variable hash (which won't be GC'd) with references to an object at creation and remove it when the client requests it. Either that, or don't instantiate transient objects until they're requested. You would have to see where the DRb objects are instantiated, in akephalos or in spork, and actually used.

jrafanie avatar May 24 '11 15:05 jrafanie

Great hint. I will boot up a new rails 3 app tonight to see if I can figure out what specifically is being GC'd then requested.

lightsofapollo avatar May 24 '11 19:05 lightsofapollo

@lightsofapollo: How did it go? Any improvements?

Nerian avatar Jun 02 '11 17:06 Nerian

Nothing yet, still working on it. Taking some time off in three weeks. I will be able to focus more on it then if I don't figure it out in my spare time before then. Like your fork by the way.

lightsofapollo avatar Jun 02 '11 17:06 lightsofapollo

I don't think this is a GC issue - the issue appears to be that when test codes talks to akephalos' remote drb object it uses the wrong uri when constructing proxy object for blocks, so ruby then tries to invoke the block in the spork parent process rather than the process actually running the features/specs (note that in the backtrace the error is thrown from druby://127.0.0.1:8989 which is the uri for the service spork advertises).

I've put a longer discussion along with a workaround that works for my cucumber specs at http://spacevatican.org/2011/7/3/sporking-with-akephalos

fcheung avatar Jul 03 '11 18:07 fcheung

@fchenung: Good work!

Nerian avatar Jul 03 '11 19:07 Nerian

@fchenung: Excellent Job. Nice write up too.

We should add this to the docs of Spork in the short term.

lightsofapollo avatar Jul 03 '11 19:07 lightsofapollo