debug icon indicating copy to clipboard operation
debug copied to clipboard

Remote debugging of `rake test` raises `Errno::EADDRINUSE`

Open suketa opened this issue 4 years ago • 6 comments

Your environment

  • ruby -v: ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]
  • rdbg -v: rdbg 1.3.4

Describe the bug remote debugging with rake test raises Errno::EADDRINUSE

To Reproduce Rakefile:

require 'rake/testtask'

Rake::TestTask.new(:test) do |t|
  t.test_files = ['test_example.rb']
end

test_example.rb:

require 'minitest/autorun'

class TestExample < Minitest::Test
  def test_foo
    binding.break
    assert_equal(true, true)
  end
end

And run in console:

$ rdbg -O -p 12345 -c rake test

And connect from another console and type c:

$ rdbg -A 12345
[5, 14] in ~/.asdf/installs/ruby/3.0.2/bin/rake
     5| # The application 'rake' is installed as part of a gem, and
     6| # this file is here to facilitate running it.
     7| #
     8|
     9|
=>  10| version = ">= 0.a"
    11|
    12| str = ARGV.first
    13| if str
    14|   str = str.b[/\A_(.*)_\z/, 1]
=>#0    <main> at ~/.asdf/installs/ruby/3.0.2/bin/rake:10
(rdbg:remote) c    # continue command

Then Errno::EADDRINUSE was raised in server console.

$ rdbg -O -p 12345 -c rake test
DEBUGGER: Debugger can attach via TCP/IP (127.0.0.1:12345)
DEBUGGER: wait for debugger connection...
DEBUGGER: Connected.
/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:131: warning: assigned but unused variable - r
DEBUGGER: wait for debugger connection...
#<Thread:0x0000562eb6c48160@DEBUGGER__::Server::reader /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:43 run> terminated with exception (report_on_exception is true):
/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `bind': Address already in use - bind(2) for 127.0.0.1:12345 (Errno::EADDRINUSE)
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `listen'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:765:in `block in tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `each'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `foreach'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:763:in `tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:338:in `accept'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:48:in `block in activate'
["DEBUGGER Exception: /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/thread_client.rb:967",
 #<Errno::EADDRINUSE: Address already in use - bind(2) for 127.0.0.1:12345>,
 ["/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `bind'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `listen'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:765:in `block in tcp_server_sockets'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `each'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `foreach'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:763:in `tcp_server_sockets'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:338:in `accept'",
  "/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:48:in `block in activate'"]]
#<Thread:0x0000562eb6c3ff60@DEBUGGER__::SESSION@server /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/session.rb:144 aborting> terminated with exception (report_on_exception is true):
/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `bind': Address already in use - bind(2) for 127.0.0.1:12345 (Errno::EADDRINUSE)
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `listen'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:765:in `block in tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `each'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `foreach'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:763:in `tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:338:in `accept'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:48:in `block in activate'
/home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `bind': Address already in use - bind(2) for 127.0.0.1:12345 (Errno::EADDRINUSE)
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:201:in `listen'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:765:in `block in tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `each'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:227:in `foreach'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/3.0.0/socket.rb:763:in `tcp_server_sockets'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:338:in `accept'
        from /home/suke/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/debug-1.3.4/lib/debug/server.rb:48:in `block in activate'
rake aborted!
Command failed with status (1)

Tasks: TOP => test
(See full trace by running task with --trace)
DEBUGGER: Disconnected.

Expected behavior

Not raise Errno::EADDRINUSE and debugger stops at binding.break line in test_example.rb.

suketa avatar Nov 06 '21 05:11 suketa

I'm not sure how the rake test invokes the test process, but I think the following scenario.

(1) Running rake with debugg port == 12345 (2) Create another process for the test (test worker) and tries to open the debug port 12345, but it's already opened at (1).

 6966 pts/0    S+     0:00 ruby /home/ko1/.rbenv/versions/2.7.3/bin/rake test
 6994 pts/0    S+     0:00 sh -c /home/ko1/.rbenv/versions/2.7.3/bin/ruby -w -I"lib" /home/ko1/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/rake-13.0.6/lib/rake/rake_test_loader.rb "test_example.rb"
 6995 pts/0    Sl+    0:00 /home/ko1/.rbenv/versions/2.7.3/bin/ruby -w -Ilib /home/ko1/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/rake-13.0.6/lib/rake/rake_test_loader.rb test_example.rb

On my environment the ps log shows 2 ruby processes are created and confirms (2).

Now I have no idea how to solve it... Hmm.

Two possible solutions:

(1) use port 0. It assigns free port randomly. (2) Disable debugger at the beginning of Rakefile (not implemented yet).

ko1 avatar Nov 08 '21 08:11 ko1

It is big change but

(3) introduce remote proxy server for remote debuggees

It seems orthodox method, but it needs a time.

ko1 avatar Nov 08 '21 08:11 ko1

Now I don't have a good solution on it.

ko1 avatar Mar 25 '22 09:03 ko1

Think I found a similar problem. See: https://github.com/connorshea/vscode-ruby-test-adapter/issues/92#issuecomment-1191477785

rubensa avatar Jul 21 '22 13:07 rubensa

Wow rdbg is used by another project ;p

ko1 avatar Jul 27 '22 06:07 ko1