teamcapybara / capybara

Acceptance test framework for web applications
http://teamcapybara.github.io/capybara/
MIT License
10.01k stars 1.45k forks source link

Ruby 2.7.1 - Errno::EMFILE: Failed to open TCP connection to 127.0.0.1:9*** (Too many open files - socket(2) for "127.0.0.1" port 9***) #2414

Closed ndbroadbent closed 3 years ago

ndbroadbent commented 3 years ago

Hello, I would like to re-open this issue that was closed and locked: https://github.com/teamcapybara/capybara/issues/2238

Since I upgraded to Ruby 2.7, I'm now seeing a lot of these errors. Example RSpec output:

Failures:

  1) Test that fails
     Failure/Error:
       expect(page).to have_content('Expected content')

     Errno::EMFILE:
       Failed to open TCP connection to 127.0.0.1:9515 (Too many open files - socket(2) for "127.0.0.1" port 9515)
     # /Users/ndbroadbent/code/capybara/lib/capybara/selenium/extensions/find.rb:17:in `find_by'
     # /Users/ndbroadbent/code/capybara/lib/capybara/selenium/extensions/find.rb:7:in `find_xpath'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/base.rb:116:in `find_xpath'
     # /Users/ndbroadbent/code/capybara/lib/capybara/queries/selector_query.rb:249:in `find_nodes_by_selector_format'
     # /Users/ndbroadbent/code/capybara/lib/capybara/queries/selector_query.rb:158:in `block in resolve_for'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/base.rb:77:in `synchronize'
     # /Users/ndbroadbent/code/capybara/lib/capybara/queries/selector_query.rb:157:in `resolve_for'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/finders.rb:294:in `block in synced_resolve'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/base.rb:77:in `synchronize'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/finders.rb:292:in `synced_resolve'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/finders.rb:53:in `find'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/document.rb:24:in `text'
     # /Users/ndbroadbent/code/capybara/lib/capybara/queries/text_query.rb:108:in `text'
     # /Users/ndbroadbent/code/capybara/lib/capybara/queries/text_query.rb:29:in `resolve_for'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/matchers.rb:862:in `block in _verify_text'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/base.rb:83:in `synchronize'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/matchers.rb:861:in `_verify_text'
     # /Users/ndbroadbent/code/capybara/lib/capybara/node/matchers.rb:676:in `assert_text'
     # /Users/ndbroadbent/code/capybara/lib/capybara/session.rb:754:in `assert_text'
     # /Users/ndbroadbent/code/capybara/lib/capybara/rspec/matchers/have_text.rb:10:in `element_matches?'
     # /Users/ndbroadbent/code/capybara/lib/capybara/rspec/matchers/base.rb:51:in `matches?'
     # ./spec/features/feature_spec.rb:166:in `block (3 levels) in <main>'
     # /Users/ndbroadbent/code/capybara/lib/capybara/session.rb:430:in `within_frame'
     # /Users/ndbroadbent/code/capybara/lib/capybara/dsl.rb:53:in `call'
     # /Users/ndbroadbent/code/capybara/lib/capybara/dsl.rb:53:in `within_frame'
     # ./spec/features/feature_spec.rb:93:in `block (2 levels) in <main>'
     # -e:1:in `<main>'
     # ------------------
     # --- Caused by: ---
     # Errno::EMFILE:
     #   Too many open files - socket(2) for "127.0.0.1" port 9515
     #   /Users/ndbroadbent/code/capybara/lib/capybara/selenium/extensions/find.rb:17:in `find_by'

Other reports around the internet:

I have been getting the same error messages with Capybara feature specs since upgrading to ruby 2.7, and it has nothing to do with open files, per se. When Capybara misses a selector (in your case, probably find('.panel.#synopsis .btn', text: /new email/i)), it throws a socket(2) too many files error.

ulimit -Sn 10240 did not solve the problem. This error doesn't happen on Ruby 2.6.

I can't remember where I read this, but I believe that it could be due to WebMock. Perhaps something is getting caught in an infinite loop and trying to open too many files?

I just wanted to open this issue in case other people are seeing this and don't have anywhere to post it. I will also work a proof-of-concept repo to demonstrate the issue, and will update the description with a link once that is ready to test.

ndbroadbent commented 3 years ago

Sorry, false alarm! The error message was actually true, and Ruby 2.7.1 must have changed something so that I started running into this file limit.

I followed the instructions here and now the problem is solved: https://medium.com/mindful-technology/too-many-open-files-limit-ulimit-on-mac-os-x-add0f1bfddde

Before:

$ launchctl limit maxfiles
    maxfiles    256            unlimited

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 256
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 11136
virtual memory          (kbytes, -v) unlimited

After:

$ launchctl limit maxfiles
    maxfiles    524288         524288

$ ulimit -a

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 524288
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 2048
virtual memory          (kbytes, -v) unlimited

Now I can run the tests and have a failing expectation without this crash.

I should also mention that I'm running macOS Catalina 10.15.7.

KirillKayumov commented 3 years ago

If anyone is experiencing the problem, take a look at the Gotchas section: https://github.com/teamcapybara/capybara#gotchas

ndbroadbent commented 3 years ago

Thanks @KirillKayumov! I hadn’t seen that before! I believe you’re referencing this:

If WebMock is enabled, you may encounter a "Too many open files" error. A simple page.find call may cause thousands of HTTP requests until the timeout occurs. By default, WebMock will cause each of these requests to spawn a new connection. To work around this problem, you may need to enable WebMock's net_http_connect_on_start: true parameter.

I am using WebMock and I still occasionally run into the “too many open files” error (especially on Ruby 2.7), so I will try the net_http_connect_on_start: true parameter