rails: listen should not listen on paths loaded from gems

I stumbled across this when I tracked the reason why I have so many fsevent_watch processes running: after starting a rails server in development mode I see a lot of fsevent_watch processes watching directories that are in gems. Since these are not supposed to change anyways they should not be watched:

/Users/eno/projects/--redacted-- [master] > ps -xf | grep fs[e]vent_watch
  501  2309  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0.1/lib/active_support/locale
  501  2310  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/activemodel-5.0.0.1/lib/active_model/locale
  501  2311  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/activerecord-5.0.0.1/lib/active_record/locale
  501  2312  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/actionview-5.0.0.1/lib/action_view/locale
  501  2313  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/responders-2.3.0/lib/responders/locales
  501  2314  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/devise-4.2.0/config/locales
  501  2315  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/kaminari-0.17.0/config/locales
  501  2316  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/projects/--redacted--/config/locales
  501  2317  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0.1
  501  2318  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/jquery-rails-4.2.1
  501  2319  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/foundation-rails-6.2.3.0/config
  501  2320  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rails-timeago-2.15.0
  501  2321  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/cloudinary-1.2.3
  501  2322  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/foundation-rails-6.2.3.0/app/controllers
  501  2323  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/devise-4.2.0/app/controllers
  501  2324  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/devise-4.2.0/app/helpers
  501  2325  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/.rvm/gems/ruby-2.3.1/gems/devise-4.2.0/app/mailers
  501  2326  2307   0  5:40PM ttys000    0:00.01 /Users/eno/.rvm/gems/ruby-2.3.1/gems/rb-fsevent-0.9.7/bin/fsevent_watch --latency 0.1 /Users/eno/projects/--redacted--

The culprit here seems to be in railsties’ lib/rails/application.rb file, which loads all the ActiveSupport::Dependencies.autoload_paths as paths to watch. In my case config.watchable_files and config.watchable_dirs is empty.

# API.
def watchable_args #:nodoc:
  files, dirs = config.watchable_files.dup, config.watchable_dirs.dup

  ActiveSupport::Dependencies.autoload_paths.each do |path|
    dirs[path.to_s] = [:rb]
  end

  [files, dirs]
end

I guess for the reason that also autoload_paths should not include paths from inside gems, but maybe I am wrong there.

In any case fixing this could also help with https://github.com/rails/rails/issues/26158 and https://github.com/jonleighton/spring-watcher-listen/issues/13

Expected behavior

Watchers should only start for the app directories itself.

Actual behavior

Watchers start for a number of directories outside of the app directory itself.

System configuration

Rails version: 5.0.0.1 Ruby version: 2.3.1 OS: Mac OS 10.11

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 26 (24 by maintainers)

Most upvoted comments

I’ve added the fix proposed by @radiospiel as a monkey patch and so far so good. There is no processes started outside the app directory. The number of active processes is down to ~15 from ~200 per app.

In case someone ends up reading thread from Google while looking for a solution - this worked for me:

config/initializers/fsevent_watch_fix.rb

module ActiveSupport
  class EventedFileUpdateChecker
    private

    def directories_to_watch
      dtw = (@files + @dirs.keys).map { |f| @ph.existing_parent(f) }
      dtw.compact!
      dtw.uniq!

      normalized_gem_paths = Gem.path.map { |path| File.join path, "" }
      dtw = dtw.reject do |path|
        normalized_gem_paths.any? { |gem_path| path.to_s.starts_with?(gem_path) }
      end

      @ph.filter_out_descendants(dtw)
    end
  end
end

Backported in 5568a77254 and 615baac6e5