guard / guard-spork

Guard::Spork automatically manage Spork DRb servers
https://rubygems.org/gems/guard-spork
MIT License
296 stars 58 forks source link

When stoping guard => spork not stoped #28

Closed niquola closed 12 years ago

niquola commented 12 years ago

is this expected behavior?

thibaudgg commented 12 years ago

no, how do you stop guard? (the good way, is 'q' + enter)

niquola commented 12 years ago

yes i stop guard this way we looked at guard and found that this is a problem of guard it doesn't call stop for guards at all (not only for spork)

thibaudgg commented 12 years ago

Normally it should do it right here, can you give your Gemfile / Guardfile

niquola commented 12 years ago

We made research and found what it breaks somewhere in this line https://github.com/guard/guard/blob/master/lib/guard.rb#L75

seems like listener.stop is failing so it doesn't reach loop with stopping guards

our working monkey patch is swapping lines (but it looks it can break something)

def Guard.stop
  UI.info "Monkey pattched bye bye...", :reset => true
  guards.each { |guard| supervised_task(guard, :stop) }
  listener.stop
  abort
end

Guardfile:

guard 'livereload',
  :api_version => '1.6',
  :host => 'localhost',
  :port => '35729',
  :apply_js_live => false,
  :apply_css_live => false,
  :grace_period => 0.5 do
    # for firefox install extension 0.6.3 or later from here: https://addons.mozilla.org/en-US/firefox/addon/livereload/versions/?page=1#version-0.6.3
    # then add LR button to toolbar, and use it when you want to connect to LR server
    watch(%r{app/.+\.(erb|haml)})
    watch(%r{app/helpers/.+\.rb})
    watch(%r{(public/|app/assets).+\.(css|js|html)})
    watch(%r{(app/assets/.+\.css)\.s[ac]ss}) { |m| m[1] }
    watch(%r{(app/assets/.+\.js)\.coffee}) { |m| m[1] }
    watch(%r{config/locales/.+\.yml})

    watch(%r{(app/stylesheets).+\.(scss)})
  end

guard 'spork', :cucumber => false, :test_unit => false do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch(%r{^config/environments/.*\.rb$})
  watch(%r{^config/initializers/.*\.rb$})
  watch('spec/spec_helper.rb')
end

guard 'rspec',
  :version => 2,
  :cli => "--drb --color",
  :bundler => true,
  :notification => true, #install libnotify gem to get notifications in linux => sudo gem install libnotify
  :all_on_start => false,
  :all_after_pass => false do

    watch(%r{^spec/.+_spec\.rb$})
    watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
    watch('spec/spec_helper.rb')  { "spec" }

    # Rails example
    watch(%r{^spec/.+_spec\.rb$})
    watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
    watch(%r{^lib/(.+)\.rb$})                           { |m| "spec/lib/#{m[1]}_spec.rb" }
    watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
    watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
    watch('spec/spec_helper.rb')                        { "spec" }
    watch('config/routes.rb')                           { "spec/routing" }
    watch('app/controllers/application_controller.rb')  { "spec/controllers" }
    # Capybara request specs
    watch(%r{^app/views/(.+)/.*\.(erb|haml)$})          { |m| "spec/requests/#{m[1]}_spec.rb" }
  end

Gemfile is too big :)

niquola commented 12 years ago

:( this monkey patch does not properly work only sometimes

thibaudgg commented 12 years ago

I think you're using rb-inotify, try to comment it in your Gemfile, to see if there is the same problem with the default polling listener.

ivalkeen commented 12 years ago

Seems that it works fine without rb-inotify

thibaudgg commented 12 years ago

Ok, so there's certainly an issue with how rb-inotify is stopped. Please can you tell me what listener.stop returns. And maybe directly open an issue on Guard. We can also add an option (true by default) to guard-spork to kill all instance of Spork on start.

partydrone commented 12 years ago

I'm seeing the same behavior. When I stop guard, it fails to kill the spork processes.

Gemfile:

source 'http://rubygems.org'

gem 'rails', '3.1.0'

# Bundle edge Rails instead:
# gem 'rails',     :git => 'git://github.com/rails/rails.git'

gem 'sqlite3', :groups => [:development, :test]
gem 'pg', :group => :staging
gem 'mysql2', :group => :production

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails', "  ~> 3.1.0"
  gem 'coffee-rails', "~> 3.1.0"
  gem 'uglifier'
end

gem 'jquery-rails'

# Use unicorn as the web server
# gem 'unicorn'

# Deploy with Capistrano
gem 'capistrano'
gem 'capistrano-ext'

# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'

group :development, :test do
  gem 'cucumber-rails'
  gem 'database_cleaner'
  gem 'factory_girl_rails'
  gem 'rspec-rails'
  gem 'selenium-client'
  gem 'spork', '~> 0.9.0.rc'
  gem 'webrat'
  gem 'rb-fsevent', :require => false if  RUBY_PLATFORM =~ /darwin/i
  gem 'guard-cucumber'
  gem 'guard-pow'
  gem 'guard-rspec'
  gem 'guard-spork'
  gem 'growl'
end

Guardfile:

# A sample Guardfile
# More info at https://github.com/guard/guard#readme

guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch(%r{^config/environments/.+\.rb$})
  watch(%r{^config/initializers/.+\.rb$})
  watch('spec/spec_helper.rb')
end

guard 'cucumber', :cli => "--drb", :all_on_start => false, :all_after_pass => false do # , :cli => "--no-profile --format 'pretty'"
  watch(%r{^features/.+\.feature$})
  watch(%r{^features/support/.+$})          { 'features' }
  watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
end

guard 'rspec', :version => 2, :cli => '--drb', :all_on_start => false, :all_after_pass => false do
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch('spec/spec_helper.rb')  { "spec" }

  # Rails example
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
  watch(%r{^lib/(.+)\.rb$})                           { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
  watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
  watch('spec/spec_helper.rb')                        { "spec" }
  watch('config/routes.rb')                           { "spec/routing" }
  watch('app/controllers/application_controller.rb')  { "spec/controllers" }
  # Capybara request specs
  watch(%r{^app/views/(.+)/.*\.(erb|haml)$})          { |m| "spec/requests/#{m[1]}_spec.rb" }
end

guard 'pow' do
  watch('.powrc')
  watch('.powenv')
  watch('.rvmrc')
  watch('Gemfile')
  watch('Gemfile.lock')
  watch('config/application.rb')
  watch('config/environment.rb')
  watch(%r{^config/environments/.*\.rb$})
  watch(%r{^config/initializers/.*\.rb$})
end

Guard startup info (guard -c -d):

Guard is now watching at '/Users/aporter/Developer/com/wavetronix/id'
DEBUG (10:20:08): Hook :start_begin executed for Guard::Spork
DEBUG (10:20:08): Killing Spork servers with PID: 
Starting Spork for RSpec & Cucumber 
DEBUG (10:20:08): Spawned Spork server 65999 ('bundle exec spork -p 8989')
DEBUG (10:20:08): Spawned Spork server 66000 ('bundle exec spork cu -p 8990')
Using Cucumber
Using RSpec
Preloading Rails environment
Preloading Rails environment
Loading Spork.prefork block...
Loading Spork.prefork block...
Spork is ready and listening on 8989!
DEPRECATION WARNING: class_inheritable_attribute is deprecated, please use class_attribute method instead. Notice their behavior are slightly different, so refer to class_attribute documentation first. (called from block in <top (required)> at /Users/aporter/Developer/com/wavetronix/id/features/support/env.rb:11)
DEPRECATION WARNING: class_inheritable_attribute is deprecated, please use class_attribute method instead. Notice their behavior are slightly different, so refer to class_attribute documentation first. (called from block in <top (required)> at /Users/aporter/Developer/com/wavetronix/id/features/support/env.rb:11)
Spork is ready and listening on 8990!
Spork server for RSpec & Cucumber successfully started
DEBUG (10:20:18): Command execution: growlnotify --version
DEBUG (10:20:18): Hook :start_end executed for Guard::Spork
DEBUG (10:20:18): Hook :start_begin executed for Guard::Cucumber
DEBUG (10:20:18): Hook :start_end executed for Guard::Cucumber
DEBUG (10:20:18): Hook :start_begin executed for Guard::RSpec
Guard::RSpec is running, with RSpec 2!
DEBUG (10:20:18): Hook :start_end executed for Guard::RSpec
DEBUG (10:20:18): Hook :start_begin executed for Guard::Pow
DEBUG (10:20:18): Hook :start_end executed for Guard::Pow

If I run all features and specs (by pressing RETURN), and then quit (by pressing q + RETURN), I see:

Bye bye...
id%

But if I just start it up (guard -c -d) and then quit right away, I get the expected behavior:

Bye bye...
DEBUG (10:21:39): Hook :stop_begin executed for Guard::Spork
DEBUG (10:21:39): Killing Spork servers with PID: 65999, 66000
DEBUG (10:21:39): Reaping spork 65999
DEBUG (10:21:39): Reaping spork 66000
DEBUG (10:21:39): Hook :stop_end executed for Guard::Spork
DEBUG (10:21:39): Hook :stop_begin executed for Guard::Cucumber
DEBUG (10:21:39): Hook :stop_end executed for Guard::Cucumber
DEBUG (10:21:39): Hook :stop_begin executed for Guard::RSpec
DEBUG (10:21:39): Hook :stop_end executed for Guard::RSpec
DEBUG (10:21:39): Hook :stop_begin executed for Guard::Pow
DEBUG (10:21:39): Hook :stop_end executed for Guard::Pow

And I will sometimes see this when quitting:

Bye bye...
/Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/rb-fsevent-0.4.3.1/lib/rb-fsevent/fsevent.rb:47:in `kill': No such process (Errno::ESRCH)
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/rb-fsevent-0.4.3.1/lib/rb-fsevent/fsevent.rb:47:in `stop'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/rb-fsevent-0.4.3.1/lib/rb-fsevent/fsevent.rb:42:in `run'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/guard-0.7.0/lib/guard/listeners/darwin.rb:15:in `start'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/guard-0.7.0/lib/guard.rb:45:in `start'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/guard-0.7.0/lib/guard/cli.rb:17:in `start'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/thor-0.14.6/lib/thor/task.rb:22:in `run'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/thor-0.14.6/lib/thor/invocation.rb:118:in `invoke_task'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/thor-0.14.6/lib/thor.rb:263:in `dispatch'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/thor-0.14.6/lib/thor/base.rb:389:in `start'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/gems/guard-0.7.0/bin/guard:6:in `<top (required)>'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/bin/guard:19:in `load'
    from /Users/aporter/.rvm/gems/ruby-1.9.2-p290@id/bin/guard:19:in `<main>'

Not quite sure why I get the sporadic behavior. For now, I just use Activity Monitor to kill the stray processes.

thibaudgg commented 12 years ago

That's weird it's working great for me (rspec only). But we maybe need a more aggressive way to found Spork pids on start. Please can you try the master branch to see if it's working now by adding:

gem 'guard-spork', :git => 'git://github.com/guard/guard-spork.git'

to your Gemfile?

partydrone commented 12 years ago

Looks good, so far. I will keep watching to see if it continues to work and let you know if I run into any issues again.

ivalkeen commented 12 years ago

listener.stop doesn't return anything. It runs until sleep(@latency) instruction and quits (seems like thread is killed, or something like that). By the way it works (spork is killed) if I remove this sleep instruction. I'm using guard 0.7.0 and guard-spork 0.2.1.

thibaudgg commented 12 years ago

And by running run_guard_task(:stop) before listener.stop does it work? (Please also try to update to guard 0.8.1 and guard-spork master)

partydrone commented 12 years ago

Monitoring the processes with Activity Monitor (Mac OS X), I can see the processes starting up like so:

Terminal [72871]
    login [72873]
        zsh [72874]
            ruby [73269] <-- This is the guard process, I believe.
                fsevent_watch [73291]
                ruby [73272] <-- Cucumber spork (port 8989)
                ruby [73273] <-- RSpec spork (port 8990)

What I've done to see this behavior is simply start guard (guard -c) and then immediately quit guard (q + RETURN), and I don't know why, but sometimes guard kills the spork processes, and sometimes it orphans them—they're no longer "owned" by any process, but they're still running. The fsevent_watch process, though, always dies.

thibaudgg commented 12 years ago

Ok after some research, I think I have found and fixed this issue. Please can you try with the master version of guard & guard-spork:

gem 'guard', :git => 'git://github.com/guard/guard.git'
gem 'guard-spork', :git => 'git://github.com/guard/guard-spork.git'
robbl commented 12 years ago

Had the same issue before and it works for me, now! Good job!

OS X 10.7.1

rails -v
Rails 3.1.0

ruby -v
ruby 1.8.7 (2011-06-30 patchlevel 352) [i686-darwin11.1.0]

gem list | grep -E -e "(spork|guard)"
guard (0.8.1)
guard-cucumber (0.6.3)
guard-rspec (0.4.5)
guard-spork (0.2.1)
spork (0.9.0.rc9)
ivalkeen commented 12 years ago

Yes, it works perfectly now. Thank you very much.

thibaudgg commented 12 years ago

Ok just released guard 0.8.2 & guard-spork 0.3.0 (that depends on guard 0.8.2). Thanks to all on this one!

partydrone commented 12 years ago

Looks good. All is right with the world. Thanks!